',
+ leftButton + centerButton + rightButton + justifyButton,
+ '
' +
+ linkButton + unlinkButton +
+ '
';
+ return tplPopover('note-link-popover', content);
+ };
+
+ var tplImagePopover = function () {
+ var fullButton = tplButton('');
+ for (var i = 0, lenGroup = group[1].length; i < lenGroup; i++) {
+ var $button = $(tplButtonInfo[group[1][i]](lang, options));
+
+ $button.attr('data-name', group[1][i]);
+
+ $group.append($button);
+ }
+ $content.append($group);
+ }
+
+ return tplPopover('note-air-popover', $content.children());
+ };
+
+ var $notePopover = $('
');
+
+ $notePopover.append(tplLinkPopover());
+ $notePopover.append(tplImagePopover());
+
+ if (options.airMode) {
+ $notePopover.append(tplAirPopover());
+ }
+
+ return $notePopover;
+ };
+
+ var tplHandles = function (options) {
+ return '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ (options.disableResizeImage ? '' : '
') +
+ '
' +
+ '
';
+ };
+
+ /**
+ * shortcut table template
+ * @param {String} title
+ * @param {String} body
+ */
+ var tplShortcut = function (title, keys) {
+ var keyClass = 'note-shortcut-col col-xs-6 note-shortcut-';
+ var body = [];
+
+ for (var i in keys) {
+ if (keys.hasOwnProperty(i)) {
+ body.push(
+ '
' + keys[i].kbd + '
' +
+ '
' + keys[i].text + '
'
+ );
+ }
+ }
+
+ return '
' +
+ '
' + body.join('
') + '
';
+ };
+
+ var tplShortcutText = function (lang) {
+ var keys = [
+ { kbd: '⌘ + B', text: lang.font.bold },
+ { kbd: '⌘ + I', text: lang.font.italic },
+ { kbd: '⌘ + U', text: lang.font.underline },
+ { kbd: '⌘ + \\', text: lang.font.clear }
+ ];
+
+ return tplShortcut(lang.shortcut.textFormatting, keys);
+ };
+
+ var tplShortcutAction = function (lang) {
+ var keys = [
+ { kbd: '⌘ + Z', text: lang.history.undo },
+ { kbd: '⌘ + ⇧ + Z', text: lang.history.redo },
+ { kbd: '⌘ + ]', text: lang.paragraph.indent },
+ { kbd: '⌘ + [', text: lang.paragraph.outdent },
+ { kbd: '⌘ + ENTER', text: lang.hr.insert }
+ ];
+
+ return tplShortcut(lang.shortcut.action, keys);
+ };
+
+ var tplShortcutPara = function (lang) {
+ var keys = [
+ { kbd: '⌘ + ⇧ + L', text: lang.paragraph.left },
+ { kbd: '⌘ + ⇧ + E', text: lang.paragraph.center },
+ { kbd: '⌘ + ⇧ + R', text: lang.paragraph.right },
+ { kbd: '⌘ + ⇧ + J', text: lang.paragraph.justify },
+ { kbd: '⌘ + ⇧ + NUM7', text: lang.lists.ordered },
+ { kbd: '⌘ + ⇧ + NUM8', text: lang.lists.unordered }
+ ];
+
+ return tplShortcut(lang.shortcut.paragraphFormatting, keys);
+ };
+
+ var tplShortcutStyle = function (lang) {
+ var keys = [
+ { kbd: '⌘ + NUM0', text: lang.style.normal },
+ { kbd: '⌘ + NUM1', text: lang.style.h1 },
+ { kbd: '⌘ + NUM2', text: lang.style.h2 },
+ { kbd: '⌘ + NUM3', text: lang.style.h3 },
+ { kbd: '⌘ + NUM4', text: lang.style.h4 },
+ { kbd: '⌘ + NUM5', text: lang.style.h5 },
+ { kbd: '⌘ + NUM6', text: lang.style.h6 }
+ ];
+
+ return tplShortcut(lang.shortcut.documentStyle, keys);
+ };
+
+ var tplExtraShortcuts = function (lang, options) {
+ var extraKeys = options.extraKeys;
+ var keys = [];
+
+ for (var key in extraKeys) {
+ if (extraKeys.hasOwnProperty(key)) {
+ keys.push({ kbd: key, text: extraKeys[key] });
+ }
+ }
+
+ return tplShortcut(lang.shortcut.extraKeys, keys);
+ };
+
+ var tplShortcutTable = function (lang, options) {
+ var colClass = 'class="note-shortcut note-shortcut-col col-sm-6 col-xs-12"';
+ var template = [
+ '
' + tplShortcutAction(lang, options) + '
' +
+ '
' + tplShortcutText(lang, options) + '
',
+ '
' + tplShortcutStyle(lang, options) + '
' +
+ '
' + tplShortcutPara(lang, options) + '
'
+ ];
+
+ if (options.extraKeys) {
+ template.push('
' + tplExtraShortcuts(lang, options) + '
');
+ }
+
+ return '
' +
+ template.join('
') +
+ '
';
+ };
+
+ var replaceMacKeys = function (sHtml) {
+ return sHtml.replace(/⌘/g, 'Ctrl').replace(/⇧/g, 'Shift');
+ };
+
+ var tplDialogInfo = {
+ image: function (lang, options) {
+ var imageLimitation = '';
+ if (options.maximumImageFileSize) {
+ var unit = Math.floor(Math.log(options.maximumImageFileSize) / Math.log(1024));
+ var readableSize = (options.maximumImageFileSize / Math.pow(1024, unit)).toFixed(2) * 1 +
+ ' ' + ' KMGTP'[unit] + 'B';
+ imageLimitation = '
' + lang.image.maximumFileSize + ' : ' + readableSize + '';
+ }
+
+ var body = '
' +
+ '' +
+ '' +
+ imageLimitation +
+ '
' +
+ '
' +
+ '' +
+ '' +
+ '
';
+ var footer = '
';
+ return tplDialog('note-image-dialog', lang.image.insert, body, footer);
+ },
+
+ link: function (lang, options) {
+ var body = '
' +
+ '' +
+ '' +
+ '
' +
+ '
' +
+ '' +
+ '' +
+ '
' +
+ (!options.disableLinkTarget ?
+ '
' +
+ '' +
+ '
' : ''
+ );
+ var footer = '
';
+ return tplDialog('note-link-dialog', lang.link.insert, body, footer);
+ },
+
+ help: function (lang, options) {
+ var body = '
' + lang.shortcut.close + '' +
+ '
' + lang.shortcut.shortcuts + '
' +
+ (agent.isMac ? tplShortcutTable(lang, options) : replaceMacKeys(tplShortcutTable(lang, options))) +
+ '
' +
+ 'Summernote 0.6.16 · ' +
+ 'Project · ' +
+ 'Issues' +
+ '
';
+ return tplDialog('note-help-dialog', '', body, '');
+ }
+ };
+
+ var tplDialogs = function (lang, options) {
+ var dialogs = '';
+
+ $.each(tplDialogInfo, function (idx, tplDialog) {
+ dialogs += tplDialog(lang, options);
+ });
+
+ return '
' + dialogs + '
';
+ };
+
+ var tplStatusbar = function () {
+ return '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
';
+ };
+
+ var representShortcut = function (str) {
+ if (agent.isMac) {
+ str = str.replace('CMD', '⌘').replace('SHIFT', '⇧');
+ }
+
+ return str.replace('BACKSLASH', '\\')
+ .replace('SLASH', '/')
+ .replace('LEFTBRACKET', '[')
+ .replace('RIGHTBRACKET', ']');
+ };
+
+ /**
+ * createTooltip
+ *
+ * @param {jQuery} $container
+ * @param {Object} keyMap
+ * @param {String} [sPlacement]
+ */
+ var createTooltip = function ($container, keyMap, sPlacement) {
+ var invertedKeyMap = func.invertObject(keyMap);
+ var $buttons = $container.find('button');
+
+ $buttons.each(function (i, elBtn) {
+ var $btn = $(elBtn);
+ var sShortcut = invertedKeyMap[$btn.data('event')];
+ if (sShortcut) {
+ $btn.attr('title', function (i, v) {
+ return v + ' (' + representShortcut(sShortcut) + ')';
+ });
+ }
+ // bootstrap tooltip on btn-group bug
+ // https://github.com/twbs/bootstrap/issues/5687
+ }).tooltip({
+ container: 'body',
+ trigger: 'hover',
+ placement: sPlacement || 'top'
+ }).on('click', function () {
+ $(this).tooltip('hide');
+ });
+ };
+
+ // createPalette
+ var createPalette = function ($container, options) {
+ var colorInfo = options.colors;
+ $container.find('.note-color-palette').each(function () {
+ var $palette = $(this), eventName = $palette.attr('data-target-event');
+ var paletteContents = [];
+ for (var row = 0, lenRow = colorInfo.length; row < lenRow; row++) {
+ var colors = colorInfo[row];
+ var buttons = [];
+ for (var col = 0, lenCol = colors.length; col < lenCol; col++) {
+ var color = colors[col];
+ buttons.push(['
'].join(''));
+ }
+ paletteContents.push('
' + buttons.join('') + '
');
+ }
+ $palette.html(paletteContents.join(''));
+ });
+ };
+
+ /**
+ * create summernote layout (air mode)
+ *
+ * @param {jQuery} $holder
+ * @param {Object} options
+ */
+ this.createLayoutByAirMode = function ($holder, options) {
+ var langInfo = options.langInfo;
+ var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];
+ var id = func.uniqueId();
+
+ $holder.addClass('note-air-editor note-editable panel-body');
+ $holder.attr({
+ 'id': 'note-editor-' + id,
+ 'contentEditable': true
+ });
+
+ var body = document.body;
+
+ // create Popover
+ var $popover = $(tplPopovers(langInfo, options));
+ $popover.addClass('note-air-layout');
+ $popover.attr('id', 'note-popover-' + id);
+ $popover.appendTo(body);
+ createTooltip($popover, keyMap);
+ createPalette($popover, options);
+
+ // create Handle
+ var $handle = $(tplHandles(options));
+ $handle.addClass('note-air-layout');
+ $handle.attr('id', 'note-handle-' + id);
+ $handle.appendTo(body);
+
+ // create Dialog
+ var $dialog = $(tplDialogs(langInfo, options));
+ $dialog.addClass('note-air-layout');
+ $dialog.attr('id', 'note-dialog-' + id);
+ $dialog.find('button.close, a.modal-close').click(function () {
+ $(this).closest('.modal').modal('hide');
+ });
+ $dialog.appendTo(body);
+ };
+
+ /**
+ * create summernote layout (normal mode)
+ *
+ * @param {jQuery} $holder
+ * @param {Object} options
+ */
+ this.createLayoutByFrame = function ($holder, options) {
+ var langInfo = options.langInfo;
+
+ //01. create Editor
+ var $editor = $('
');
+ if (options.width) {
+ $editor.width(options.width);
+ }
+
+ //02. statusbar (resizebar)
+ if (options.height > 0) {
+ $('
' + (options.disableResizeEditor ? '' : tplStatusbar()) + '
').prependTo($editor);
+ }
+
+ //03 editing area
+ var $editingArea = $('
');
+ //03. create editable
+ var isContentEditable = !$holder.is(':disabled');
+ var $editable = $('
').prependTo($editingArea);
+
+ if (options.height) {
+ $editable.height(options.height);
+ }
+ if (options.direction) {
+ $editable.attr('dir', options.direction);
+ }
+ var placeholder = $holder.attr('placeholder') || options.placeholder;
+ if (placeholder) {
+ $editable.attr('data-placeholder', placeholder);
+ }
+
+ $editable.html(dom.html($holder) || dom.emptyPara);
+
+ //031. create codable
+ $('
').prependTo($editingArea);
+
+ //04. create Popover
+ var $popover = $(tplPopovers(langInfo, options)).prependTo($editingArea);
+ createPalette($popover, options);
+ createTooltip($popover, keyMap);
+
+ //05. handle(control selection, ...)
+ $(tplHandles(options)).prependTo($editingArea);
+
+ $editingArea.prependTo($editor);
+
+ //06. create Toolbar
+ var $toolbar = $('
');
+ for (var idx = 0, len = options.toolbar.length; idx < len; idx ++) {
+ var groupName = options.toolbar[idx][0];
+ var groupButtons = options.toolbar[idx][1];
+
+ var $group = $('
');
+ for (var i = 0, btnLength = groupButtons.length; i < btnLength; i++) {
+ var buttonInfo = tplButtonInfo[groupButtons[i]];
+ // continue creating toolbar even if a button doesn't exist
+ if (!$.isFunction(buttonInfo)) { continue; }
+
+ var $button = $(buttonInfo(langInfo, options));
+ $button.attr('data-name', groupButtons[i]); // set button's alias, becuase to get button element from $toolbar
+ $group.append($button);
+ }
+ $toolbar.append($group);
+ }
+
+ var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];
+ createPalette($toolbar, options);
+ createTooltip($toolbar, keyMap, 'bottom');
+ $toolbar.prependTo($editor);
+
+ //07. create Dropzone
+ $('
').prependTo($editor);
+
+ //08. create Dialog
+ var $dialogContainer = options.dialogsInBody ? $(document.body) : $editor;
+ var $dialog = $(tplDialogs(langInfo, options)).prependTo($dialogContainer);
+ $dialog.find('button.close, a.modal-close').click(function () {
+ $(this).closest('.modal').modal('hide');
+ });
+
+ //09. Editor/Holder switch
+ $editor.insertAfter($holder);
+ $holder.hide();
+ };
+
+ this.hasNoteEditor = function ($holder) {
+ return this.noteEditorFromHolder($holder).length > 0;
+ };
+
+ this.noteEditorFromHolder = function ($holder) {
+ if ($holder.hasClass('note-air-editor')) {
+ return $holder;
+ } else if ($holder.next().hasClass('note-editor')) {
+ return $holder.next();
+ } else {
+ return $();
+ }
+ };
+
+ /**
+ * create summernote layout
+ *
+ * @param {jQuery} $holder
+ * @param {Object} options
+ */
+ this.createLayout = function ($holder, options) {
+ if (options.airMode) {
+ this.createLayoutByAirMode($holder, options);
+ } else {
+ this.createLayoutByFrame($holder, options);
+ }
+ };
+
+ /**
+ * returns layoutInfo from holder
+ *
+ * @param {jQuery} $holder - placeholder
+ * @return {Object}
+ */
+ this.layoutInfoFromHolder = function ($holder) {
+ var $editor = this.noteEditorFromHolder($holder);
+ if (!$editor.length) {
+ return;
+ }
+
+ // connect $holder to $editor
+ $editor.data('holder', $holder);
+
+ return dom.buildLayoutInfo($editor);
+ };
+
+ /**
+ * removeLayout
+ *
+ * @param {jQuery} $holder - placeholder
+ * @param {Object} layoutInfo
+ * @param {Object} options
+ *
+ */
+ this.removeLayout = function ($holder, layoutInfo, options) {
+ if (options.airMode) {
+ $holder.removeClass('note-air-editor note-editable')
+ .removeAttr('id contentEditable');
+
+ layoutInfo.popover().remove();
+ layoutInfo.handle().remove();
+ layoutInfo.dialog().remove();
+ } else {
+ $holder.html(layoutInfo.editable().html());
+
+ if (options.dialogsInBody) {
+ layoutInfo.dialog().remove();
+ }
+ layoutInfo.editor().remove();
+ $holder.show();
+ }
+ };
+
+ /**
+ *
+ * @return {Object}
+ * @return {function(label, options=):string} return.button {@link #tplButton function to make text button}
+ * @return {function(iconClass, options=):string} return.iconButton {@link #tplIconButton function to make icon button}
+ * @return {function(className, title=, body=, footer=):string} return.dialog {@link #tplDialog function to make dialog}
+ */
+ this.getTemplate = function () {
+ return {
+ button: tplButton,
+ iconButton: tplIconButton,
+ dialog: tplDialog
+ };
+ };
+
+ /**
+ * add button information
+ *
+ * @param {String} name button name
+ * @param {Function} buttonInfo function to make button, reference to {@link #tplButton},{@link #tplIconButton}
+ */
+ this.addButtonInfo = function (name, buttonInfo) {
+ tplButtonInfo[name] = buttonInfo;
+ };
+
+ /**
+ *
+ * @param {String} name
+ * @param {Function} dialogInfo function to make dialog, reference to {@link #tplDialog}
+ */
+ this.addDialogInfo = function (name, dialogInfo) {
+ tplDialogInfo[name] = dialogInfo;
+ };
+ };
+
+
+ // jQuery namespace for summernote
+ /**
+ * @class $.summernote
+ *
+ * summernote attribute
+ *
+ * @mixin defaults
+ * @singleton
+ *
+ */
+ $.summernote = $.summernote || {};
+
+ // extends default settings
+ // - $.summernote.version
+ // - $.summernote.options
+ // - $.summernote.lang
+ $.extend($.summernote, defaults);
+
+ var renderer = new Renderer();
+ var eventHandler = new EventHandler();
+
+ $.extend($.summernote, {
+ /** @property {Renderer} */
+ renderer: renderer,
+ /** @property {EventHandler} */
+ eventHandler: eventHandler,
+ /**
+ * @property {Object} core
+ * @property {core.agent} core.agent
+ * @property {core.dom} core.dom
+ * @property {core.range} core.range
+ */
+ core: {
+ agent: agent,
+ list : list,
+ dom: dom,
+ range: range
+ },
+ /**
+ * @property {Object}
+ * pluginEvents event list for plugins
+ * event has name and callback function.
+ *
+ * ```
+ * $.summernote.addPlugin({
+ * events : {
+ * 'hello' : function(layoutInfo, value, $target) {
+ * console.log('event name is hello, value is ' + value );
+ * }
+ * }
+ * })
+ * ```
+ *
+ * * event name is data-event property.
+ * * layoutInfo is a summernote layout information.
+ * * value is data-value property.
+ */
+ pluginEvents: {},
+
+ plugins : []
+ });
+
+ /**
+ * @method addPlugin
+ *
+ * add Plugin in Summernote
+ *
+ * Summernote can make a own plugin.
+ *
+ * ### Define plugin
+ * ```
+ * // get template function
+ * var tmpl = $.summernote.renderer.getTemplate();
+ *
+ * // add a button
+ * $.summernote.addPlugin({
+ * buttons : {
+ * // "hello" is button's namespace.
+ * "hello" : function(lang, options) {
+ * // make icon button by template function
+ * return tmpl.iconButton(options.iconPrefix + 'header', {
+ * // callback function name when button clicked
+ * event : 'hello',
+ * // set data-value property
+ * value : 'hello',
+ * hide : true
+ * });
+ * }
+ *
+ * },
+ *
+ * events : {
+ * "hello" : function(layoutInfo, value) {
+ * // here is event code
+ * }
+ * }
+ * });
+ * ```
+ * ### Use a plugin in toolbar
+ *
+ * ```
+ * $("#editor").summernote({
+ * ...
+ * toolbar : [
+ * // display hello plugin in toolbar
+ * ['group', [ 'hello' ]]
+ * ]
+ * ...
+ * });
+ * ```
+ *
+ *
+ * @param {Object} plugin
+ * @param {Object} [plugin.buttons] define plugin button. for detail, see to Renderer.addButtonInfo
+ * @param {Object} [plugin.dialogs] define plugin dialog. for detail, see to Renderer.addDialogInfo
+ * @param {Object} [plugin.events] add event in $.summernote.pluginEvents
+ * @param {Object} [plugin.langs] update $.summernote.lang
+ * @param {Object} [plugin.options] update $.summernote.options
+ */
+ $.summernote.addPlugin = function (plugin) {
+
+ // save plugin list
+ $.summernote.plugins.push(plugin);
+
+ if (plugin.buttons) {
+ $.each(plugin.buttons, function (name, button) {
+ renderer.addButtonInfo(name, button);
+ });
+ }
+
+ if (plugin.dialogs) {
+ $.each(plugin.dialogs, function (name, dialog) {
+ renderer.addDialogInfo(name, dialog);
+ });
+ }
+
+ if (plugin.events) {
+ $.each(plugin.events, function (name, event) {
+ $.summernote.pluginEvents[name] = event;
+ });
+ }
+
+ if (plugin.langs) {
+ $.each(plugin.langs, function (locale, lang) {
+ if ($.summernote.lang[locale]) {
+ $.extend($.summernote.lang[locale], lang);
+ }
+ });
+ }
+
+ if (plugin.options) {
+ $.extend($.summernote.options, plugin.options);
+ }
+ };
+
+ /*
+ * extend $.fn
+ */
+ $.fn.extend({
+ /**
+ * @method
+ * Initialize summernote
+ * - create editor layout and attach Mouse and keyboard events.
+ *
+ * ```
+ * $("#summernote").summernote( { options ..} );
+ * ```
+ *
+ * @member $.fn
+ * @param {Object|String} options reference to $.summernote.options
+ * @return {this}
+ */
+ summernote: function () {
+ // check first argument's type
+ // - {String}: External API call {{module}}.{{method}}
+ // - {Object}: init options
+ var type = $.type(list.head(arguments));
+ var isExternalAPICalled = type === 'string';
+ var hasInitOptions = type === 'object';
+
+ // extend default options with custom user options
+ var options = hasInitOptions ? list.head(arguments) : {};
+
+ options = $.extend({}, $.summernote.options, options);
+ options.icons = $.extend({}, $.summernote.options.icons, options.icons);
+
+ // Include langInfo in options for later use, e.g. for image drag-n-drop
+ // Setup language info with en-US as default
+ options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]);
+
+ // override plugin options
+ if (!isExternalAPICalled && hasInitOptions) {
+ for (var i = 0, len = $.summernote.plugins.length; i < len; i++) {
+ var plugin = $.summernote.plugins[i];
+
+ if (options.plugin[plugin.name]) {
+ $.summernote.plugins[i] = $.extend(true, plugin, options.plugin[plugin.name]);
+ }
+ }
+ }
+
+ this.each(function (idx, holder) {
+ var $holder = $(holder);
+
+ // if layout isn't created yet, createLayout and attach events
+ if (!renderer.hasNoteEditor($holder)) {
+ renderer.createLayout($holder, options);
+
+ var layoutInfo = renderer.layoutInfoFromHolder($holder);
+ $holder.data('layoutInfo', layoutInfo);
+
+ eventHandler.attach(layoutInfo, options);
+ eventHandler.attachCustomEvent(layoutInfo, options);
+ }
+ });
+
+ var $first = this.first();
+ if ($first.length) {
+ var layoutInfo = renderer.layoutInfoFromHolder($first);
+
+ // external API
+ if (isExternalAPICalled) {
+ var moduleAndMethod = list.head(list.from(arguments));
+ var args = list.tail(list.from(arguments));
+
+ // TODO now external API only works for editor
+ var params = [moduleAndMethod, layoutInfo.editable()].concat(args);
+ return eventHandler.invoke.apply(eventHandler, params);
+ } else if (options.focus) {
+ // focus on first editable element for initialize editor
+ layoutInfo.editable().focus();
+ }
+ }
+
+ return this;
+ },
+
+ /**
+ * @method
+ *
+ * get the HTML contents of note or set the HTML contents of note.
+ *
+ * * get contents
+ * ```
+ * var content = $("#summernote").code();
+ * ```
+ * * set contents
+ *
+ * ```
+ * $("#summernote").code(html);
+ * ```
+ *
+ * @member $.fn
+ * @param {String} [html] - HTML contents(optional, set)
+ * @return {this|String} - context(set) or HTML contents of note(get).
+ */
+ code: function (html) {
+ // get the HTML contents of note
+ if (html === undefined) {
+ var $holder = this.first();
+ if (!$holder.length) {
+ return;
+ }
+
+ var layoutInfo = renderer.layoutInfoFromHolder($holder);
+ var $editable = layoutInfo && layoutInfo.editable();
+
+ if ($editable && $editable.length) {
+ var isCodeview = eventHandler.invoke('codeview.isActivated', layoutInfo);
+ eventHandler.invoke('codeview.sync', layoutInfo);
+ return isCodeview ? layoutInfo.codable().val() :
+ layoutInfo.editable().html();
+ }
+ return dom.value($holder);
+ }
+
+ // set the HTML contents of note
+ this.each(function (i, holder) {
+ var layoutInfo = renderer.layoutInfoFromHolder($(holder));
+ var $editable = layoutInfo && layoutInfo.editable();
+ if ($editable) {
+ $editable.html(html);
+ }
+ });
+
+ return this;
+ },
+
+ /**
+ * @method
+ *
+ * destroy Editor Layout and detach Key and Mouse Event
+ *
+ * @member $.fn
+ * @return {this}
+ */
+ destroy: function () {
+ this.each(function (idx, holder) {
+ var $holder = $(holder);
+
+ if (!renderer.hasNoteEditor($holder)) {
+ return;
+ }
+
+ var info = renderer.layoutInfoFromHolder($holder);
+ var options = info.editor().data('options');
+
+ eventHandler.detach(info, options);
+ renderer.removeLayout($holder, info, options);
+ });
+
+ return this;
+ }
+ });
+}));
diff --git a/bower_components/summernote/dist/summernote.min.js b/bower_components/summernote/dist/summernote.min.js
new file mode 100644
index 000000000..3cfd6775a
--- /dev/null
+++ b/bower_components/summernote/dist/summernote.min.js
@@ -0,0 +1,4 @@
+/*! Summernote v0.6.16 | (c) 2013-2015 Alan Hong and other contributors | MIT license */
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(window.jQuery)}(function(a){Array.prototype.reduce||(Array.prototype.reduce=function(a){var b,c=Object(this),d=c.length>>>0,e=0;if(2===arguments.length)b=arguments[1];else{for(;d>e&&!(e in c);)e++;if(e>=d)throw new TypeError("Reduce of empty array with no initial value");b=c[e++]}for(;d>e;e++)e in c&&(b=a(b,c[e],e,c));return b}),"function"!=typeof Array.prototype.filter&&(Array.prototype.filter=function(a){for(var b=Object(this),c=b.length>>>0,d=[],e=arguments.length>=2?arguments[1]:void 0,f=0;c>f;f++)if(f in b){var g=b[f];a.call(e,g,f,b)&&d.push(g)}return d}),Array.prototype.map||(Array.prototype.map=function(a,b){var c,d,e;if(null===this)throw new TypeError(" this is null or not defined");var f=Object(this),g=f.length>>>0;if("function"!=typeof a)throw new TypeError(a+" is not a function");for(arguments.length>1&&(c=b),d=new Array(g),e=0;g>e;){var h,i;e in f&&(h=f[e],i=a.call(c,h,e,f),d[e]=i),e++}return d});var b,c="function"==typeof define&&define.amd,d=function(b){var c="Comic Sans MS"===b?"Courier New":"Comic Sans MS",d=a("
").css({position:"absolute",left:"-9999px",top:"-9999px",fontSize:"200px"}).text("mmmmmmmmmwwwwwww").appendTo(document.body),e=d.css("fontFamily",c).width(),f=d.css("fontFamily",b+","+c).width();return d.remove(),e!==f},e=navigator.userAgent,f=/MSIE|Trident/i.test(e);if(f){var g=/MSIE (\d+[.]\d+)/.exec(e);g&&(b=parseFloat(g[1])),g=/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(e),g&&(b=parseFloat(g[1]))}var h,i={isMac:navigator.appVersion.indexOf("Mac")>-1,isMSIE:f,isFF:/firefox/i.test(e),isWebkit:/webkit/i.test(e),isSafari:/safari/i.test(e),browserVersion:b,jqueryVersion:parseFloat(a.fn.jquery),isSupportAmd:c,hasCodeMirror:c?require.specified("CodeMirror"):!!window.CodeMirror,isFontInstalled:d,isW3CRangeSupport:!!document.createRange},j=function(){var b=function(a){return function(b){return a===b}},c=function(a,b){return a===b},d=function(a){return function(b,c){return b[a]===c[a]}},e=function(){return!0},f=function(){return!1},g=function(a){return function(){return!a.apply(a,arguments)}},h=function(a,b){return function(c){return a(c)&&b(c)}},i=function(a){return a},j=0,k=function(a){var b=++j+"";return a?a+b:b},l=function(b){var c=a(document);return{top:b.top+c.scrollTop(),left:b.left+c.scrollLeft(),width:b.right-b.left,height:b.bottom-b.top}},m=function(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[a[c]]=c);return b},n=function(a,b){return b=b||"",b+a.split(".").map(function(a){return a.substring(0,1).toUpperCase()+a.substring(1)}).join("")};return{eq:b,eq2:c,peq2:d,ok:e,fail:f,self:i,not:g,and:h,uniqueId:k,rect2bnd:l,invertObject:m,namespaceToCamel:n}}(),k=function(){var b=function(a){return a[0]},c=function(a){return a[a.length-1]},d=function(a){return a.slice(0,a.length-1)},e=function(a){return a.slice(1)},f=function(a,b){for(var c=0,d=a.length;d>c;c++){var e=a[c];if(b(e))return e}},g=function(a,b){for(var c=0,d=a.length;d>c;c++)if(!b(a[c]))return!1;return!0},h=function(b,c){return a.inArray(c,b)},i=function(a,b){return-1!==h(a,b)},k=function(a,b){return b=b||j.self,a.reduce(function(a,c){return a+b(c)},0)},l=function(a){for(var b=[],c=-1,d=a.length;++c
c;c++)a[c]&&b.push(a[c]);return b},o=function(a){for(var b=[],c=0,d=a.length;d>c;c++)i(b,a[c])||b.push(a[c]);return b},p=function(a,b){var c=h(a,b);return-1===c?null:a[c+1]},q=function(a,b){var c=h(a,b);return-1===c?null:a[c-1]};return{head:b,last:c,initial:d,tail:e,prev:q,next:p,find:f,contains:i,all:g,sum:k,from:l,clusterBy:m,compact:n,unique:o}}(),l=String.fromCharCode(160),m="\ufeff",n=function(){var b=function(b){return b&&a(b).hasClass("note-editable")},c=function(b){return b&&a(b).hasClass("note-control-sizing")},d=function(b){var c;if(b.hasClass("note-air-editor")){var d=k.last(b.attr("id").split("-"));return c=function(b){return function(){return a(b+d)}},{editor:function(){return b},holder:function(){return b.data("holder")},editable:function(){return b},popover:c("#note-popover-"),handle:c("#note-handle-"),dialog:c("#note-dialog-")}}c=function(a,c){return c=c||b,function(){return c.find(a)}};var e=b.data("options"),f=e&&e.dialogsInBody?a(document.body):null;return{editor:function(){return b},holder:function(){return b.data("holder")},dropzone:c(".note-dropzone"),toolbar:c(".note-toolbar"),editable:c(".note-editable"),codable:c(".note-codable"),statusbar:c(".note-statusbar"),popover:c(".note-popover"),handle:c(".note-handle"),dialog:c(".note-dialog",f)}},e=function(b){var c=a(b).closest(".note-editor, .note-air-editor, .note-air-layout");if(!c.length)return null;var e;return e=c.is(".note-editor, .note-air-editor")?c:a("#note-editor-"+k.last(c.attr("id").split("-"))),d(e)},f=function(a){return a=a.toUpperCase(),function(b){return b&&b.nodeName.toUpperCase()===a}},g=function(a){return a&&3===a.nodeType},h=function(a){return a&&/^BR|^IMG|^HR|^IFRAME|^BUTTON/.test(a.nodeName.toUpperCase())},o=function(a){return b(a)?!1:a&&/^DIV|^P|^LI|^H[1-7]/.test(a.nodeName.toUpperCase())},p=f("LI"),q=function(a){return o(a)&&!p(a)},r=f("TABLE"),s=function(a){return!(x(a)||t(a)||u(a)||o(a)||r(a)||w(a))},t=function(a){return a&&/^UL|^OL/.test(a.nodeName.toUpperCase())},u=f("HR"),v=function(a){return a&&/^TD|^TH/.test(a.nodeName.toUpperCase())},w=f("BLOCKQUOTE"),x=function(a){return v(a)||w(a)||b(a)},y=f("A"),z=function(a){return s(a)&&!!I(a,o)},A=function(a){return s(a)&&!I(a,o)},B=f("BODY"),C=function(a,b){return a.nextSibling===b||a.previousSibling===b},D=function(a,b){b=b||j.ok;var c=[];return a.previousSibling&&b(a.previousSibling)&&c.push(a.previousSibling),c.push(a),a.nextSibling&&b(a.nextSibling)&&c.push(a.nextSibling),c},E=i.isMSIE&&i.browserVersion<11?" ":"
",F=function(a){return g(a)?a.nodeValue.length:a.childNodes.length},G=function(a){var b=F(a);return 0===b?!0:g(a)||1!==b||a.innerHTML!==E?k.all(a.childNodes,g)&&""===a.innerHTML?!0:!1:!0},H=function(a){h(a)||F(a)||(a.innerHTML=E)},I=function(a,c){for(;a;){if(c(a))return a;if(b(a))break;a=a.parentNode}return null},J=function(a,c){for(a=a.parentNode;a&&1===F(a);){if(c(a))return a;if(b(a))break;a=a.parentNode}return null},K=function(a,c){c=c||j.fail;var d=[];return I(a,function(a){return b(a)||d.push(a),c(a)}),d},L=function(a,b){var c=K(a);return k.last(c.filter(b))},M=function(b,c){for(var d=K(b),e=c;e;e=e.parentNode)if(a.inArray(e,d)>-1)return e;return null},N=function(a,b){b=b||j.fail;for(var c=[];a&&!b(a);)c.push(a),a=a.previousSibling;return c},O=function(a,b){b=b||j.fail;for(var c=[];a&&!b(a);)c.push(a),a=a.nextSibling;return c},P=function(a,b){var c=[];return b=b||j.ok,function d(e){a!==e&&b(e)&&c.push(e);for(var f=0,g=e.childNodes.length;g>f;f++)d(e.childNodes[f])}(a),c},Q=function(b,c){var d=b.parentNode,e=a("<"+c+">")[0];return d.insertBefore(e,b),e.appendChild(b),e},R=function(a,b){var c=b.nextSibling,d=b.parentNode;return c?d.insertBefore(a,c):d.appendChild(a),a},S=function(b,c){return a.each(c,function(a,c){b.appendChild(c)}),b},T=function(a){return 0===a.offset},U=function(a){return a.offset===F(a.node)},V=function(a){return T(a)||U(a)},W=function(a,b){for(;a&&a!==b;){if(0!==$(a))return!1;a=a.parentNode}return!0},X=function(a,b){for(;a&&a!==b;){if($(a)!==F(a.parentNode)-1)return!1;a=a.parentNode}return!0},Y=function(a,b){return T(a)&&W(a.node,b)},Z=function(a,b){return U(a)&&X(a.node,b)},$=function(a){for(var b=0;a=a.previousSibling;)b+=1;return b},_=function(a){return!!(a&&a.childNodes&&a.childNodes.length)},aa=function(a,c){var d,e;if(0===a.offset){if(b(a.node))return null;d=a.node.parentNode,e=$(a.node)}else _(a.node)?(d=a.node.childNodes[a.offset-1],e=F(d)):(d=a.node,e=c?0:a.offset-1);return{node:d,offset:e}},ba=function(a,c){var d,e;if(F(a.node)===a.offset){if(b(a.node))return null;d=a.node.parentNode,e=$(a.node)+1}else _(a.node)?(d=a.node.childNodes[a.offset],e=0):(d=a.node,e=c?F(a.node):a.offset+1);return{node:d,offset:e}},ca=function(a,b){return a.node===b.node&&a.offset===b.offset},da=function(a){if(g(a.node)||!_(a.node)||G(a.node))return!0;var b=a.node.childNodes[a.offset-1],c=a.node.childNodes[a.offset];return b&&!h(b)||c&&!h(c)?!1:!0},ea=function(a,b){for(;a;){if(b(a))return a;a=aa(a)}return null},fa=function(a,b){for(;a;){if(b(a))return a;a=ba(a)}return null},ga=function(a){if(!g(a.node))return!1;var b=a.node.nodeValue.charAt(a.offset-1);return b&&" "!==b&&b!==l},ha=function(a,b,c,d){for(var e=a;e&&(c(e),!ca(e,b));){var f=d&&a.node!==e.node&&b.node!==e.node;e=ba(e,f)}},ia=function(a,b){var c=K(b,j.eq(a));return c.map($).reverse()},ja=function(a,b){for(var c=a,d=0,e=b.length;e>d;d++)c=c.childNodes.length<=b[d]?c.childNodes[c.childNodes.length-1]:c.childNodes[b[d]];return c},ka=function(a,b){var c=b&&b.isSkipPaddingBlankHTML,d=b&&b.isNotSplitEdgePoint;if(V(a)&&(g(a.node)||d)){if(T(a))return a.node;if(U(a))return a.node.nextSibling}if(g(a.node))return a.node.splitText(a.offset);var e=a.node.childNodes[a.offset],f=R(a.node.cloneNode(!1),a.node);return S(f,O(e)),c||(H(a.node),H(f)),f},la=function(a,b,c){var d=K(b.node,j.eq(a));return d.length?1===d.length?ka(b,c):d.reduce(function(a,d){return a===b.node&&(a=ka(b,c)),ka({node:d,offset:a?n.position(a):F(d)},c)}):null},ma=function(a,b){var c,d,e=b?o:x,f=K(a.node,e),g=k.last(f)||a.node;e(g)?(c=f[f.length-2],d=g):(c=g,d=c.parentNode);var h=c&&la(c,a,{isSkipPaddingBlankHTML:b,isNotSplitEdgePoint:b});return h||d!==a.node||(h=a.node.childNodes[a.offset]),{rightNode:h,container:d}},na=function(a){return document.createElement(a)},oa=function(a){return document.createTextNode(a)},pa=function(a,b){if(a&&a.parentNode){if(a.removeNode)return a.removeNode(b);var c=a.parentNode;if(!b){var d,e,f=[];for(d=0,e=a.childNodes.length;e>d;d++)f.push(a.childNodes[d]);for(d=0,e=f.length;e>d;d++)c.insertBefore(f[d],a)}c.removeChild(a)}},qa=function(a,c){for(;a&&!b(a)&&c(a);){var d=a.parentNode;pa(a),a=d}},ra=function(a,b){if(a.nodeName.toUpperCase()===b.toUpperCase())return a;var c=na(b);return a.style.cssText&&(c.style.cssText=a.style.cssText),S(c,k.from(a.childNodes)),R(c,a),pa(a),c},sa=f("TEXTAREA"),ta=function(a,b){var c=sa(a[0])?a.val():a.html();return b?c.replace(/[\n\r]/g,""):c},ua=function(b,c){var d=ta(b);if(c){var e=/<(\/?)(\b(?!!)[^>\s]*)(.*?)(\s*\/?>)/g;d=d.replace(e,function(a,b,c){c=c.toUpperCase();var d=/^DIV|^TD|^TH|^P|^LI|^H[1-7]/.test(c)&&!!b,e=/^BLOCKQUOTE|^TABLE|^TBODY|^TR|^HR|^UL|^OL/.test(c);return a+(d||e?"\n":"")}),d=a.trim(d)}return d};return{NBSP_CHAR:l,ZERO_WIDTH_NBSP_CHAR:m,blank:E,emptyPara:""+E+"
",makePredByNodeName:f,isEditable:b,isControlSizing:c,buildLayoutInfo:d,makeLayoutInfo:e,isText:g,isVoid:h,isPara:o,isPurePara:q,isInline:s,isBlock:j.not(s),isBodyInline:A,isBody:B,isParaInline:z,isList:t,isTable:r,isCell:v,isBlockquote:w,isBodyContainer:x,isAnchor:y,isDiv:f("DIV"),isLi:p,isBR:f("BR"),isSpan:f("SPAN"),isB:f("B"),isU:f("U"),isS:f("S"),isI:f("I"),isImg:f("IMG"),isTextarea:sa,isEmpty:G,isEmptyAnchor:j.and(y,G),isClosestSibling:C,withClosestSiblings:D,nodeLength:F,isLeftEdgePoint:T,isRightEdgePoint:U,isEdgePoint:V,isLeftEdgeOf:W,isRightEdgeOf:X,isLeftEdgePointOf:Y,isRightEdgePointOf:Z,prevPoint:aa,nextPoint:ba,isSamePoint:ca,isVisiblePoint:da,prevPointUntil:ea,nextPointUntil:fa,isCharPoint:ga,walkPoint:ha,ancestor:I,singleChildAncestor:J,listAncestor:K,lastAncestor:L,listNext:O,listPrev:N,listDescendant:P,commonAncestor:M,wrap:Q,insertAfter:R,appendChildNodes:S,position:$,hasChildren:_,makeOffsetPath:ia,fromOffsetPath:ja,splitTree:la,splitPoint:ma,create:na,createText:oa,remove:pa,removeWhile:qa,replace:ra,html:ua,value:ta}}(),o=function(){var b=function(a,b){var c,d,e=a.parentElement(),f=document.body.createTextRange(),g=k.from(e.childNodes);for(c=0;c=0)break;d=g[c]}if(0!==c&&n.isText(g[c-1])){var h=document.body.createTextRange(),i=null;h.moveToElementText(d||e),h.collapse(!d),i=d?d.nextSibling:e.firstChild;var j=a.duplicate();j.setEndPoint("StartToStart",h);for(var l=j.text.replace(/[\r\n]/g,"").length;l>i.nodeValue.length&&i.nextSibling;)l-=i.nodeValue.length,i=i.nextSibling;i.nodeValue;b&&i.nextSibling&&n.isText(i.nextSibling)&&l===i.nodeValue.length&&(l-=i.nodeValue.length,i=i.nextSibling),e=i,c=l}return{cont:e,offset:c}},c=function(a){var b=function(a,c){var d,e;if(n.isText(a)){var f=n.listPrev(a,j.not(n.isText)),g=k.last(f).previousSibling;d=g||a.parentNode,c+=k.sum(k.tail(f),n.nodeLength),e=!g}else{if(d=a.childNodes[c]||a,n.isText(d))return b(d,0);c=0,e=!1}return{node:d,collapseToStart:e,offset:c}},c=document.body.createTextRange(),d=b(a.node,a.offset);return c.moveToElementText(d.node),c.collapse(d.collapseToStart),c.moveStart("character",d.offset),c},d=function(b,e,f,g){this.sc=b,this.so=e,this.ec=f,this.eo=g;var h=function(){if(i.isW3CRangeSupport){var a=document.createRange();return a.setStart(b,e),a.setEnd(f,g),a}var d=c({node:b,offset:e});return d.setEndPoint("EndToEnd",c({node:f,offset:g})),d};this.getPoints=function(){return{sc:b,so:e,ec:f,eo:g}},this.getStartPoint=function(){return{node:b,offset:e}},this.getEndPoint=function(){return{node:f,offset:g}},this.select=function(){var a=h();if(i.isW3CRangeSupport){var b=document.getSelection();b.rangeCount>0&&b.removeAllRanges(),b.addRange(a)}else a.select();return this},this.normalize=function(){var a=function(a,b){if(n.isVisiblePoint(a)&&!n.isEdgePoint(a)||n.isVisiblePoint(a)&&n.isRightEdgePoint(a)&&!b||n.isVisiblePoint(a)&&n.isLeftEdgePoint(a)&&b||n.isVisiblePoint(a)&&n.isBlock(a.node)&&n.isEmpty(a.node))return a;var c=n.ancestor(a.node,n.isBlock);if((n.isLeftEdgePointOf(a,c)||n.isVoid(n.prevPoint(a).node))&&!b||(n.isRightEdgePointOf(a,c)||n.isVoid(n.nextPoint(a).node))&&b){if(n.isVisiblePoint(a))return a;b=!b}var d=b?n.nextPointUntil(n.nextPoint(a),n.isVisiblePoint):n.prevPointUntil(n.prevPoint(a),n.isVisiblePoint);return d||a},b=a(this.getEndPoint(),!1),c=this.isCollapsed()?b:a(this.getStartPoint(),!0);return new d(c.node,c.offset,b.node,b.offset)},this.nodes=function(a,b){a=a||j.ok;var c=b&&b.includeAncestor,d=b&&b.fullyContains,e=this.getStartPoint(),f=this.getEndPoint(),g=[],h=[];return n.walkPoint(e,f,function(b){if(!n.isEditable(b.node)){var e;d?(n.isLeftEdgePoint(b)&&h.push(b.node),n.isRightEdgePoint(b)&&k.contains(h,b.node)&&(e=b.node)):e=c?n.ancestor(b.node,a):b.node,e&&a(e)&&g.push(e)}},!0),k.unique(g)},this.commonAncestor=function(){return n.commonAncestor(b,f)},this.expand=function(a){var c=n.ancestor(b,a),h=n.ancestor(f,a);if(!c&&!h)return new d(b,e,f,g);var i=this.getPoints();return c&&(i.sc=c,i.so=0),h&&(i.ec=h,i.eo=n.nodeLength(h)),new d(i.sc,i.so,i.ec,i.eo)},this.collapse=function(a){return a?new d(b,e,b,e):new d(f,g,f,g)},this.splitText=function(){var a=b===f,c=this.getPoints();return n.isText(f)&&!n.isEdgePoint(this.getEndPoint())&&f.splitText(g),n.isText(b)&&!n.isEdgePoint(this.getStartPoint())&&(c.sc=b.splitText(e),c.so=0,a&&(c.ec=c.sc,c.eo=g-e)),new d(c.sc,c.so,c.ec,c.eo)},this.deleteContents=function(){if(this.isCollapsed())return this;var b=this.splitText(),c=b.nodes(null,{fullyContains:!0}),e=n.prevPointUntil(b.getStartPoint(),function(a){return!k.contains(c,a.node)}),f=[];return a.each(c,function(a,b){var c=b.parentNode;e.node!==c&&1===n.nodeLength(c)&&f.push(c),n.remove(b,!1)}),a.each(f,function(a,b){n.remove(b,!1)}),new d(e.node,e.offset,e.node,e.offset).normalize()};var l=function(a){return function(){var c=n.ancestor(b,a);return!!c&&c===n.ancestor(f,a)}};this.isOnEditable=l(n.isEditable),this.isOnList=l(n.isList),this.isOnAnchor=l(n.isAnchor),this.isOnCell=l(n.isCell),this.isLeftEdgeOf=function(a){if(!n.isLeftEdgePoint(this.getStartPoint()))return!1;var b=n.ancestor(this.sc,a);return b&&n.isLeftEdgeOf(this.sc,b)},this.isCollapsed=function(){return b===f&&e===g},this.wrapBodyInlineWithPara=function(){if(n.isBodyContainer(b)&&n.isEmpty(b))return b.innerHTML=n.emptyPara,new d(b.firstChild,0,b.firstChild,0);var a=this.normalize();if(n.isParaInline(b)||n.isPara(b))return a;var c;if(n.isInline(a.sc)){var e=n.listAncestor(a.sc,j.not(n.isInline));c=k.last(e),n.isInline(c)||(c=e[e.length-2]||a.sc.childNodes[a.so])}else c=a.sc.childNodes[a.so>0?a.so-1:0];var f=n.listPrev(c,n.isParaInline).reverse();if(f=f.concat(n.listNext(c.nextSibling,n.isParaInline)),f.length){var g=n.wrap(k.head(f),"p");n.appendChildNodes(g,k.tail(f))}return this.normalize()},this.insertNode=function(a){var b=this.wrapBodyInlineWithPara().deleteContents(),c=n.splitPoint(b.getStartPoint(),n.isInline(a));return c.rightNode?c.rightNode.parentNode.insertBefore(a,c.rightNode):c.container.appendChild(a),a},this.pasteHTML=function(b){var c=a("").html(b)[0],d=k.from(c.childNodes),e=this.wrapBodyInlineWithPara().deleteContents();return d.reverse().map(function(a){return e.insertNode(a)}).reverse()},this.toString=function(){var a=h();return i.isW3CRangeSupport?a.toString():a.text},this.getWordRange=function(a){var b=this.getEndPoint();if(!n.isCharPoint(b))return this;var c=n.prevPointUntil(b,function(a){return!n.isCharPoint(a)});return a&&(b=n.nextPointUntil(b,function(a){return!n.isCharPoint(a)})),new d(c.node,c.offset,b.node,b.offset)},this.bookmark=function(a){return{s:{path:n.makeOffsetPath(a,b),offset:e},e:{path:n.makeOffsetPath(a,f),offset:g}}},this.paraBookmark=function(a){return{s:{path:k.tail(n.makeOffsetPath(k.head(a),b)),offset:e},e:{path:k.tail(n.makeOffsetPath(k.last(a),f)),offset:g}}},this.getClientRects=function(){var a=h();return a.getClientRects()}};return{create:function(a,c,e,f){if(arguments.length)2===arguments.length&&(e=a,f=c);else if(i.isW3CRangeSupport){var g=document.getSelection();if(!g||0===g.rangeCount)return null;if(n.isBody(g.anchorNode))return null;var h=g.getRangeAt(0);a=h.startContainer,c=h.startOffset,e=h.endContainer,f=h.endOffset}else{var j=document.selection.createRange(),k=j.duplicate();k.collapse(!1);var l=j;l.collapse(!0);var m=b(l,!0),o=b(k,!1);n.isText(m.node)&&n.isLeftEdgePoint(m)&&n.isTextNode(o.node)&&n.isRightEdgePoint(o)&&o.node.nextSibling===m.node&&(m=o),a=m.cont,c=m.offset,e=o.cont,f=o.offset}return new d(a,c,e,f)},createFromNode:function(a){var b=a,c=0,d=a,e=n.nodeLength(d);return n.isVoid(b)&&(c=n.listPrev(b).length-1,b=b.parentNode),n.isBR(d)?(e=n.listPrev(d).length-1,d=d.parentNode):n.isVoid(d)&&(e=n.listPrev(d).length,d=d.parentNode),this.create(b,c,d,e)},createFromNodeBefore:function(a){return this.createFromNode(a).collapse(!0)},createFromNodeAfter:function(a){return this.createFromNode(a).collapse()},createFromBookmark:function(a,b){var c=n.fromOffsetPath(a,b.s.path),e=b.s.offset,f=n.fromOffsetPath(a,b.e.path),g=b.e.offset;return new d(c,e,f,g)},createFromParaBookmark:function(a,b){var c=a.s.offset,e=a.e.offset,f=n.fromOffsetPath(k.head(b),a.s.path),g=n.fromOffsetPath(k.last(b),a.e.path);return new d(f,c,g,e)}}}(),p={version:"0.6.16",options:{width:null,height:null,minHeight:null,maxHeight:null,focus:!1,tabsize:4,styleWithSpan:!0,disableLinkTarget:!1,disableDragAndDrop:!1,disableResizeEditor:!1,disableResizeImage:!1,shortcuts:!0,textareaAutoSync:!0,placeholder:!1,prettifyHtml:!0,iconPrefix:"fa fa-",icons:{font:{bold:"bold",italic:"italic",underline:"underline",clear:"eraser",height:"text-height",strikethrough:"strikethrough",superscript:"superscript",subscript:"subscript"},image:{image:"picture-o",floatLeft:"align-left",floatRight:"align-right",floatNone:"align-justify",shapeRounded:"square",shapeCircle:"circle-o",shapeThumbnail:"picture-o",shapeNone:"times",remove:"trash-o"},link:{link:"link",unlink:"unlink",edit:"edit"},table:{table:"table"},hr:{insert:"minus"},style:{style:"magic"},lists:{unordered:"list-ul",ordered:"list-ol"},options:{help:"question",fullscreen:"arrows-alt",codeview:"code"},paragraph:{paragraph:"align-left",outdent:"outdent",indent:"indent",left:"align-left",center:"align-center",right:"align-right",justify:"align-justify"},color:{recent:"font"},history:{undo:"undo",redo:"repeat"},misc:{check:"check"}},dialogsInBody:!1,codemirror:{mode:"text/html",htmlMode:!0,lineNumbers:!0},lang:"en-US",direction:null,toolbar:[["style",["style"]],["font",["bold","italic","underline","clear"]],["fontname",["fontname"]],["fontsize",["fontsize"]],["color",["color"]],["para",["ul","ol","paragraph"]],["height",["height"]],["table",["table"]],["insert",["link","picture","hr"]],["view",["fullscreen","codeview"]],["help",["help"]]],plugin:{},airMode:!1,airPopover:[["color",["color"]],["font",["bold","underline","clear"]],["para",["ul","paragraph"]],["table",["table"]],["insert",["link","picture"]]],styleTags:["p","blockquote","pre","h1","h2","h3","h4","h5","h6"],defaultFontName:"Helvetica Neue",fontNames:["Arial","Arial Black","Comic Sans MS","Courier New","Helvetica Neue","Helvetica","Impact","Lucida Grande","Tahoma","Times New Roman","Verdana"],fontNamesIgnoreCheck:[],fontSizes:["8","9","10","11","12","14","18","24","36"],colors:[["#000000","#424242","#636363","#9C9C94","#CEC6CE","#EFEFEF","#F7F7F7","#FFFFFF"],["#FF0000","#FF9C00","#FFFF00","#00FF00","#00FFFF","#0000FF","#9C00FF","#FF00FF"],["#F7C6CE","#FFE7CE","#FFEFC6","#D6EFD6","#CEDEE7","#CEE7F7","#D6D6E7","#E7D6DE"],["#E79C9C","#FFC69C","#FFE79C","#B5D6A5","#A5C6CE","#9CC6EF","#B5A5D6","#D6A5BD"],["#E76363","#F7AD6B","#FFD663","#94BD7B","#73A5AD","#6BADDE","#8C7BC6","#C67BA5"],["#CE0000","#E79439","#EFC631","#6BA54A","#4A7B8C","#3984C6","#634AA5","#A54A7B"],["#9C0000","#B56308","#BD9400","#397B21","#104A5A","#085294","#311873","#731842"],["#630000","#7B3900","#846300","#295218","#083139","#003163","#21104A","#4A1031"]],lineHeights:["1.0","1.2","1.4","1.5","1.6","1.8","2.0","3.0"],insertTableMaxSize:{col:10,row:10},maximumImageFileSize:null,oninit:null,onfocus:null,onblur:null,onenter:null,onkeyup:null,onkeydown:null,onImageUpload:null,onImageUploadError:null,onMediaDelete:null,onToolbarClick:null,onsubmit:null,onCreateLink:function(a){return-1!==a.indexOf("@")&&-1===a.indexOf(":")&&(a="mailto:"+a),a},keyMap:{pc:{ENTER:"insertParagraph","CTRL+Z":"undo","CTRL+Y":"redo",TAB:"tab","SHIFT+TAB":"untab","CTRL+B":"bold","CTRL+I":"italic","CTRL+U":"underline","CTRL+SHIFT+S":"strikethrough","CTRL+BACKSLASH":"removeFormat","CTRL+SHIFT+L":"justifyLeft","CTRL+SHIFT+E":"justifyCenter","CTRL+SHIFT+R":"justifyRight","CTRL+SHIFT+J":"justifyFull","CTRL+SHIFT+NUM7":"insertUnorderedList","CTRL+SHIFT+NUM8":"insertOrderedList","CTRL+LEFTBRACKET":"outdent","CTRL+RIGHTBRACKET":"indent","CTRL+NUM0":"formatPara","CTRL+NUM1":"formatH1","CTRL+NUM2":"formatH2","CTRL+NUM3":"formatH3","CTRL+NUM4":"formatH4","CTRL+NUM5":"formatH5","CTRL+NUM6":"formatH6","CTRL+ENTER":"insertHorizontalRule","CTRL+K":"showLinkDialog"},mac:{ENTER:"insertParagraph","CMD+Z":"undo","CMD+SHIFT+Z":"redo",TAB:"tab","SHIFT+TAB":"untab","CMD+B":"bold","CMD+I":"italic","CMD+U":"underline","CMD+SHIFT+S":"strikethrough","CMD+BACKSLASH":"removeFormat","CMD+SHIFT+L":"justifyLeft","CMD+SHIFT+E":"justifyCenter","CMD+SHIFT+R":"justifyRight","CMD+SHIFT+J":"justifyFull","CMD+SHIFT+NUM7":"insertUnorderedList","CMD+SHIFT+NUM8":"insertOrderedList","CMD+LEFTBRACKET":"outdent","CMD+RIGHTBRACKET":"indent","CMD+NUM0":"formatPara","CMD+NUM1":"formatH1","CMD+NUM2":"formatH2","CMD+NUM3":"formatH3","CMD+NUM4":"formatH4","CMD+NUM5":"formatH5","CMD+NUM6":"formatH6","CMD+ENTER":"insertHorizontalRule","CMD+K":"showLinkDialog"}}},lang:{"en-US":{font:{bold:"Bold",italic:"Italic",underline:"Underline",clear:"Remove Font Style",height:"Line Height",name:"Font Family",strikethrough:"Strikethrough",subscript:"Subscript",superscript:"Superscript",size:"Font Size"},image:{image:"Picture",insert:"Insert Image",resizeFull:"Resize Full",resizeHalf:"Resize Half",resizeQuarter:"Resize Quarter",floatLeft:"Float Left",floatRight:"Float Right",floatNone:"Float None",shapeRounded:"Shape: Rounded",shapeCircle:"Shape: Circle",shapeThumbnail:"Shape: Thumbnail",shapeNone:"Shape: None",dragImageHere:"Drag image or text here",dropImage:"Drop image or Text",selectFromFiles:"Select from files",maximumFileSize:"Maximum file size",maximumFileSizeError:"Maximum file size exceeded.",url:"Image URL",remove:"Remove Image"},link:{link:"Link",insert:"Insert Link",unlink:"Unlink",edit:"Edit",textToDisplay:"Text to display",url:"To what URL should this link go?",openInNewWindow:"Open in new window"},table:{table:"Table"},hr:{insert:"Insert Horizontal Rule"},style:{style:"Style",normal:"Normal",blockquote:"Quote",pre:"Code",h1:"Header 1",h2:"Header 2",h3:"Header 3",h4:"Header 4",h5:"Header 5",h6:"Header 6"},lists:{unordered:"Unordered list",ordered:"Ordered list"},options:{help:"Help",fullscreen:"Full Screen",codeview:"Code View"},paragraph:{paragraph:"Paragraph",outdent:"Outdent",indent:"Indent",left:"Align left",center:"Align center",right:"Align right",justify:"Justify full"},color:{recent:"Recent Color",more:"More Color",background:"Background Color",foreground:"Foreground Color",transparent:"Transparent",setTransparent:"Set transparent",reset:"Reset",resetToDefault:"Reset to default"},shortcut:{shortcuts:"Keyboard shortcuts",close:"Close",textFormatting:"Text formatting",action:"Action",paragraphFormatting:"Paragraph formatting",documentStyle:"Document Style",extraKeys:"Extra keys"},history:{undo:"Undo",redo:"Redo"}}}},q=function(){var b=function(b){return a.Deferred(function(c){a.extend(new FileReader,{onload:function(a){var b=a.target.result;c.resolve(b)},onerror:function(){c.reject(this)}}).readAsDataURL(b)}).promise()},c=function(b,c){return a.Deferred(function(d){var e=a("");e.one("load",function(){e.off("error abort"),d.resolve(e)}).one("error abort",function(){e.off("load").detach(),d.reject(e)}).css({display:"none"}).appendTo(document.body).attr({src:b,"data-filename":c})}).promise()};return{readFileAsDataURL:b,createImage:c}}(),r=function(){var a={BACKSPACE:8,TAB:9,ENTER:13,SPACE:32,NUM0:48,NUM1:49,NUM2:50,NUM3:51,NUM4:52,NUM5:53,NUM6:54,NUM7:55,NUM8:56,B:66,E:69,I:73,J:74,K:75,L:76,R:82,S:83,U:85,V:86,Y:89,Z:90,SLASH:191,LEFTBRACKET:219,BACKSLASH:220,RIGHTBRACKET:221};return{isEdit:function(a){return k.contains([8,9,13,32],a)},isMove:function(a){return k.contains([37,38,39,40],a)},nameFromCode:j.invertObject(a),code:a}}(),s=function(a){var b=[],c=-1,d=a[0],e=function(){var b=o.create(),c={s:{path:[],offset:0},e:{path:[],offset:0}};return{contents:a.html(),bookmark:b?b.bookmark(d):c}},f=function(b){null!==b.contents&&a.html(b.contents),null!==b.bookmark&&o.createFromBookmark(d,b.bookmark).select()};this.undo=function(){a.html()!==b[c].contents&&this.recordUndo(),c>0&&(c--,f(b[c]))},this.redo=function(){b.length-1>c&&(c++,f(b[c]))},this.recordUndo=function(){c++,b.length>c&&(b=b.slice(0,c)),b.push(e())},this.recordUndo()},t=function(){var b=function(b,c){if(i.jqueryVersion<1.9){var d={};return a.each(c,function(a,c){d[c]=b.css(c)}),d}return b.css.call(b,c)};this.fromNode=function(a){var c=["font-family","font-size","text-align","list-style-type","line-height"],d=b(a,c)||{};return d["font-size"]=parseInt(d["font-size"],10),d},this.stylePara=function(b,c){a.each(b.nodes(n.isPara,{includeAncestor:!0}),function(b,d){a(d).css(c)})},this.styleNodes=function(b,c){b=b.splitText();var d=c&&c.nodeName||"SPAN",e=!(!c||!c.expandClosestSibling),f=!(!c||!c.onlyPartialContains);if(b.isCollapsed())return[b.insertNode(n.create(d))];var g=n.makePredByNodeName(d),h=b.nodes(n.isText,{fullyContains:!0}).map(function(a){return n.singleChildAncestor(a,g)||n.wrap(a,d)});if(e){if(f){var i=b.nodes();g=j.and(g,function(a){return k.contains(i,a)})}return h.map(function(b){var c=n.withClosestSiblings(b,g),d=k.head(c),e=k.tail(c);return a.each(e,function(a,b){n.appendChildNodes(d,b.childNodes),n.remove(b)}),k.head(c)})}return h},this.current=function(b){var c=a(n.isText(b.sc)?b.sc.parentNode:b.sc),d=this.fromNode(c);if(d["font-bold"]=document.queryCommandState("bold")?"bold":"normal",d["font-italic"]=document.queryCommandState("italic")?"italic":"normal",d["font-underline"]=document.queryCommandState("underline")?"underline":"normal",d["font-strikethrough"]=document.queryCommandState("strikeThrough")?"strikethrough":"normal",d["font-superscript"]=document.queryCommandState("superscript")?"superscript":"normal",d["font-subscript"]=document.queryCommandState("subscript")?"subscript":"normal",b.isOnList()){var e=["circle","disc","disc-leading-zero","square"],f=a.inArray(d["list-style-type"],e)>-1;d["list-style"]=f?"unordered":"ordered"}else d["list-style"]="none";var g=n.ancestor(b.sc,n.isPara);if(g&&g.style["line-height"])d["line-height"]=g.style.lineHeight;else{var h=parseInt(d["line-height"],10)/parseInt(d["font-size"],10);d["line-height"]=h.toFixed(1)}return d.anchor=b.isOnAnchor()&&n.ancestor(b.sc,n.isAnchor),d.ancestors=n.listAncestor(b.sc,n.isEditable),d.range=b,d}},u=function(){this.insertOrderedList=function(){this.toggleList("OL")},this.insertUnorderedList=function(){this.toggleList("UL")},this.indent=function(){var b=this,c=o.create().wrapBodyInlineWithPara(),d=c.nodes(n.isPara,{includeAncestor:!0}),e=k.clusterBy(d,j.peq2("parentNode"));a.each(e,function(c,d){var e=k.head(d);n.isLi(e)?b.wrapList(d,e.parentNode.nodeName):a.each(d,function(b,c){a(c).css("marginLeft",function(a,b){return(parseInt(b,10)||0)+25})})}),c.select()},this.outdent=function(){var b=this,c=o.create().wrapBodyInlineWithPara(),d=c.nodes(n.isPara,{includeAncestor:!0}),e=k.clusterBy(d,j.peq2("parentNode"));a.each(e,function(c,d){var e=k.head(d);n.isLi(e)?b.releaseList([d]):a.each(d,function(b,c){a(c).css("marginLeft",function(a,b){return b=parseInt(b,10)||0,b>25?b-25:""})})}),c.select()},this.toggleList=function(b){var c=this,d=o.create().wrapBodyInlineWithPara(),e=d.nodes(n.isPara,{includeAncestor:!0}),f=d.paraBookmark(e),g=k.clusterBy(e,j.peq2("parentNode"));if(k.find(e,n.isPurePara)){var h=[];a.each(g,function(a,d){h=h.concat(c.wrapList(d,b))}),e=h}else{var i=d.nodes(n.isList,{includeAncestor:!0}).filter(function(c){return!a.nodeName(c,b)});i.length?a.each(i,function(a,c){n.replace(c,b)}):e=this.releaseList(g,!0)}o.createFromParaBookmark(f,e).select()},this.wrapList=function(a,b){var c=k.head(a),d=k.last(a),e=n.isList(c.previousSibling)&&c.previousSibling,f=n.isList(d.nextSibling)&&d.nextSibling,g=e||n.insertAfter(n.create(b||"UL"),d);return a=a.map(function(a){return n.isPurePara(a)?n.replace(a,"LI"):a}),n.appendChildNodes(g,a),f&&(n.appendChildNodes(g,k.from(f.childNodes)),n.remove(f)),a},this.releaseList=function(b,c){var d=[];return a.each(b,function(b,e){var f=k.head(e),g=k.last(e),h=c?n.lastAncestor(f,n.isList):f.parentNode,i=h.childNodes.length>1?n.splitTree(h,{node:g.parentNode,offset:n.position(g)+1},{isSkipPaddingBlankHTML:!0}):null,j=n.splitTree(h,{node:f.parentNode,offset:n.position(f)},{isSkipPaddingBlankHTML:!0});e=c?n.listDescendant(j,n.isLi):k.from(j.childNodes).filter(n.isLi),(c||!n.isList(h.parentNode))&&(e=e.map(function(a){return n.replace(a,"P")})),a.each(k.from(e).reverse(),function(a,b){n.insertAfter(b,h)});var l=k.compact([h,j,i]);a.each(l,function(b,c){var d=[c].concat(n.listDescendant(c,n.isList));a.each(d.reverse(),function(a,b){n.nodeLength(b)||n.remove(b,!0)})}),d=d.concat(e)}),d}},v=function(){var b=new u;this.insertTab=function(a,b,c){var d=n.createText(new Array(c+1).join(n.NBSP_CHAR));b=b.deleteContents(),b.insertNode(d,!0),b=o.create(d,c),b.select()},this.insertParagraph=function(){var c=o.create();c=c.deleteContents(),c=c.wrapBodyInlineWithPara();var d,e=n.ancestor(c.sc,n.isPara);if(e){if(n.isEmpty(e)&&n.isLi(e))return void b.toggleList(e.parentNode.nodeName);d=n.splitTree(e,c.getStartPoint());var f=n.listDescendant(e,n.isEmptyAnchor);f=f.concat(n.listDescendant(d,n.isEmptyAnchor)),a.each(f,function(a,b){n.remove(b)})}else{var g=c.sc.childNodes[c.so];d=a(n.emptyPara)[0],g?c.sc.insertBefore(d,g):c.sc.appendChild(d)}o.create(d,0).normalize().select()}},w=function(){this.tab=function(a,b){var c=n.ancestor(a.commonAncestor(),n.isCell),d=n.ancestor(c,n.isTable),e=n.listDescendant(d,n.isCell),f=k[b?"prev":"next"](e,c);
+f&&o.create(f,0).select()},this.createTable=function(b,c){for(var d,e=[],f=0;b>f;f++)e.push(""+n.blank+" | ");d=e.join("");for(var g,h=[],i=0;c>i;i++)h.push(""+d+"
");return g=h.join(""),a('")[0]}},x="bogus",y=function(b){var c=this,d=new t,e=new w,f=new v,g=new u;this.createRange=function(a){return this.focus(a),o.create()},this.saveRange=function(a,b){this.focus(a),a.data("range",o.create()),b&&o.create().collapse().select()},this.saveNode=function(a){for(var b=[],c=0,d=a[0].childNodes.length;d>c;c++)b.push(a[0].childNodes[c]);a.data("childNodes",b)},this.restoreRange=function(a){var b=a.data("range");b&&(b.select(),this.focus(a))},this.restoreNode=function(a){a.html("");for(var b=a.data("childNodes"),c=0,d=b.length;d>c;c++)a[0].appendChild(b[c])},this.currentStyle=function(a){var b=o.create(),c=b&&b.isOnEditable()?d.current(b.normalize()):{};return n.isImg(a)&&(c.image=a),c},this.styleFromNode=function(a){return d.fromNode(a)};var h=function(a){var c=n.makeLayoutInfo(a).holder();b.bindCustomEvent(c,a.data("callbacks"),"before.command")(a.html(),a)},j=function(a){var c=n.makeLayoutInfo(a).holder();b.bindCustomEvent(c,a.data("callbacks"),"change")(a.html(),a)};this.undo=function(a){h(a),a.data("NoteHistory").undo(),j(a)},this.redo=function(a){h(a),a.data("NoteHistory").redo(),j(a)};for(var l=this.beforeCommand=function(a){h(a),c.focus(a)},m=this.afterCommand=function(a,b){a.data("NoteHistory").recordUndo(),b||j(a)},p=["bold","italic","underline","strikethrough","superscript","subscript","justifyLeft","justifyCenter","justifyRight","justifyFull","formatBlock","removeFormat","backColor","foreColor","fontName"],r=0,s=p.length;s>r;r++)this[p[r]]=function(a){return function(b,c){l(b),document.execCommand(a,!1,c),m(b,!0)}}(p[r]);this.tab=function(a,b){var c=this.createRange(a);c.isCollapsed()&&c.isOnCell()?e.tab(c):(l(a),f.insertTab(a,c,b.tabsize),m(a))},this.untab=function(a){var b=this.createRange(a);b.isCollapsed()&&b.isOnCell()&&e.tab(b,!0)},this.insertParagraph=function(a){l(a),f.insertParagraph(a),m(a)},this.insertOrderedList=function(a){l(a),g.insertOrderedList(a),m(a)},this.insertUnorderedList=function(a){l(a),g.insertUnorderedList(a),m(a)},this.indent=function(a){l(a),g.indent(a),m(a)},this.outdent=function(a){l(a),g.outdent(a),m(a)},this.insertImage=function(a,c,d){q.createImage(c,d).then(function(b){l(a),b.css({display:"",width:Math.min(a.width(),b.width())}),o.create().insertNode(b[0]),o.createFromNodeAfter(b[0]).select(),m(a)}).fail(function(){var c=n.makeLayoutInfo(a).holder();b.bindCustomEvent(c,a.data("callbacks"),"image.upload.error")()})},this.insertNode=function(a,b){l(a),o.create().insertNode(b),o.createFromNodeAfter(b).select(),m(a)},this.insertText=function(a,b){l(a);var c=o.create().insertNode(n.createText(b));o.create(c,n.nodeLength(c)).select(),m(a)},this.pasteHTML=function(a,b){l(a);var c=o.create().pasteHTML(b);o.createFromNodeAfter(k.last(c)).select(),m(a)},this.formatBlock=function(a,b){l(a),b=i.isMSIE?"<"+b+">":b,document.execCommand("FormatBlock",!1,b),m(a)},this.formatPara=function(a){l(a),this.formatBlock(a,"P"),m(a)};for(var r=1;6>=r;r++)this["formatH"+r]=function(a){return function(b){this.formatBlock(b,"H"+a)}}(r);this.fontSize=function(b,c){var e=o.create();if(e.isCollapsed()){var f=d.styleNodes(e),g=k.head(f);a(f).css({"font-size":c+"px"}),g&&!n.nodeLength(g)&&(g.innerHTML=n.ZERO_WIDTH_NBSP_CHAR,o.createFromNodeAfter(g.firstChild).select(),b.data(x,g))}else l(b),a(d.styleNodes(e)).css({"font-size":c+"px"}),m(b)},this.insertHorizontalRule=function(b){l(b);var c=o.create(),d=c.insertNode(a("
")[0]);d.nextSibling&&o.create(d.nextSibling,0).normalize().select(),m(b)},this.removeBogus=function(a){var b=a.data(x);if(b){var c=k.find(k.from(b.childNodes),n.isText),d=c.nodeValue.indexOf(n.ZERO_WIDTH_NBSP_CHAR);-1!==d&&c.deleteData(d,1),n.isEmpty(b)&&n.remove(b),a.removeData(x)}},this.lineHeight=function(a,b){l(a),d.stylePara(o.create(),{lineHeight:b}),m(a)},this.unlink=function(a){var b=this.createRange(a);if(b.isOnAnchor()){var c=n.ancestor(b.sc,n.isAnchor);b=o.createFromNode(c),b.select(),l(a),document.execCommand("unlink"),m(a)}},this.createLink=function(b,c,e){var f=c.url,g=c.text,h=c.isNewWindow,i=c.range||this.createRange(b),j=i.toString()!==g;e=e||n.makeLayoutInfo(b).editor().data("options"),l(b),e.onCreateLink&&(f=e.onCreateLink(f));var p=[];if(j){var q=i.insertNode(a(""+g+"")[0]);p.push(q)}else p=d.styleNodes(i,{nodeName:"A",expandClosestSibling:!0,onlyPartialContains:!0});a.each(p,function(b,c){a(c).attr("href",f),h?a(c).attr("target","_blank"):a(c).removeAttr("target")});var r=o.createFromNodeBefore(k.head(p)),s=r.getStartPoint(),t=o.createFromNodeAfter(k.last(p)),u=t.getEndPoint();o.create(s.node,s.offset,u.node,u.offset).select(),m(b)},this.getLinkInfo=function(b){this.focus(b);var c=o.create().expand(n.isAnchor),d=a(k.head(c.nodes(n.isAnchor)));return{range:c,text:c.toString(),isNewWindow:d.length?"_blank"===d.attr("target"):!1,url:d.length?d.attr("href"):""}},this.color=function(a,b){var c=JSON.parse(b),d=c.foreColor,e=c.backColor;l(a),d&&document.execCommand("foreColor",!1,d),e&&document.execCommand("backColor",!1,e),m(a)},this.insertTable=function(a,b){var c=b.split("x");l(a);var d=o.create().deleteContents();d.insertNode(e.createTable(c[0],c[1])),m(a)},this.floatMe=function(a,b,c){l(a),c.removeClass("pull-left pull-right"),b&&"none"!==b&&c.addClass("pull-"+b),c.css("float",b),m(a)},this.imageShape=function(a,b,c){l(a),c.removeClass("img-rounded img-circle img-thumbnail"),b&&c.addClass(b),m(a)},this.resize=function(a,b,c){l(a),c.css({width:100*b+"%",height:""}),m(a)},this.resizeTo=function(a,b,c){var d;if(c){var e=a.y/a.x,f=b.data("ratio");d={width:f>e?a.x:a.y/f,height:f>e?a.x*f:a.y}}else d={width:a.x,height:a.y};b.css(d)},this.removeMedia=function(c,d,e){l(c),e.detach(),b.bindCustomEvent(a(),c.data("callbacks"),"media.delete")(e,c),m(c)},this.focus=function(a){a.focus(),i.isFF&&!o.create().isOnEditable()&&o.createFromNode(a[0]).normalize().collapse().select()},this.isEmpty=function(a){return n.isEmpty(a[0])||n.emptyPara===a.html()}},z=function(){this.update=function(b,c){var d=function(b,c){b.find(".dropdown-menu li a").each(function(){var b=a(this).data("value")+""==c+"";this.className=b?"checked":""})},e=function(a,c){var d=b.find(a);d.toggleClass("active",c())};if(c.image){var f=a(c.image);e('button[data-event="imageShape"][data-value="img-rounded"]',function(){return f.hasClass("img-rounded")}),e('button[data-event="imageShape"][data-value="img-circle"]',function(){return f.hasClass("img-circle")}),e('button[data-event="imageShape"][data-value="img-thumbnail"]',function(){return f.hasClass("img-thumbnail")}),e('button[data-event="imageShape"]:not([data-value])',function(){return!f.is(".img-rounded, .img-circle, .img-thumbnail")});var g=f.css("float");e('button[data-event="floatMe"][data-value="left"]',function(){return"left"===g}),e('button[data-event="floatMe"][data-value="right"]',function(){return"right"===g}),e('button[data-event="floatMe"][data-value="none"]',function(){return"left"!==g&&"right"!==g});var h=f.attr("style");return e('button[data-event="resize"][data-value="1"]',function(){return!!/(^|\s)(max-)?width\s*:\s*100%/.test(h)}),e('button[data-event="resize"][data-value="0.5"]',function(){return!!/(^|\s)(max-)?width\s*:\s*50%/.test(h)}),void e('button[data-event="resize"][data-value="0.25"]',function(){return!!/(^|\s)(max-)?width\s*:\s*25%/.test(h)})}var j=b.find(".note-fontname");if(j.length){var k=c["font-family"];if(k){for(var l=k.split(","),m=0,n=l.length;n>m&&(k=l[m].replace(/[\'\"]/g,"").replace(/\s+$/,"").replace(/^\s+/,""),!i.isFontInstalled(k));m++);j.find(".note-current-fontname").text(k),d(j,k)}}var o=b.find(".note-fontsize");o.find(".note-current-fontsize").text(c["font-size"]),d(o,parseFloat(c["font-size"]));var p=b.find(".note-height");d(p,parseFloat(c["line-height"])),e('button[data-event="bold"]',function(){return"bold"===c["font-bold"]}),e('button[data-event="italic"]',function(){return"italic"===c["font-italic"]}),e('button[data-event="underline"]',function(){return"underline"===c["font-underline"]}),e('button[data-event="strikethrough"]',function(){return"strikethrough"===c["font-strikethrough"]}),e('button[data-event="superscript"]',function(){return"superscript"===c["font-superscript"]}),e('button[data-event="subscript"]',function(){return"subscript"===c["font-subscript"]}),e('button[data-event="justifyLeft"]',function(){return"left"===c["text-align"]||"start"===c["text-align"]}),e('button[data-event="justifyCenter"]',function(){return"center"===c["text-align"]}),e('button[data-event="justifyRight"]',function(){return"right"===c["text-align"]}),e('button[data-event="justifyFull"]',function(){return"justify"===c["text-align"]}),e('button[data-event="insertUnorderedList"]',function(){return"unordered"===c["list-style"]}),e('button[data-event="insertOrderedList"]',function(){return"ordered"===c["list-style"]})},this.updateRecentColor=function(b,c,d){var e=a(b).closest(".note-color"),f=e.find(".note-recent-color"),g=JSON.parse(f.attr("data-value"));g[c]=d,f.attr("data-value",JSON.stringify(g));var h="backColor"===c?"background-color":"color";f.find("i").css(h,d)}},A=function(){var a=new z;this.update=function(b,c){a.update(b,c)},this.updateRecentColor=function(b,c,d){a.updateRecentColor(b,c,d)},this.activate=function(a){a.find("button").not('button[data-event="codeview"]').removeClass("disabled")},this.deactivate=function(a){a.find("button").not('button[data-event="codeview"]').addClass("disabled")},this.updateFullscreen=function(a,b){var c=a.find('button[data-event="fullscreen"]');c.toggleClass("active",b)},this.updateCodeview=function(a,b){var c=a.find('button[data-event="codeview"]');c.toggleClass("active",b),b?this.deactivate(a):this.activate(a)},this.get=function(a,b){var c=n.makeLayoutInfo(a).toolbar();return c.find("[data-name="+b+"]")},this.setButtonState=function(a,b,c){c=c===!1?!1:!0;var d=this.get(a,b);d.toggleClass("active",c)}},B=24,C=function(){var b=a(document);this.attach=function(a,b){b.disableResizeEditor||a.statusbar().on("mousedown",c)};var c=function(a){a.preventDefault(),a.stopPropagation();var c=n.makeLayoutInfo(a.target).editable(),d=c.offset().top-b.scrollTop(),e=n.makeLayoutInfo(a.currentTarget||a.target),f=e.editor().data("options");b.on("mousemove",function(a){var b=a.clientY-(d+B);b=f.minHeight>0?Math.max(b,f.minHeight):b,b=f.maxHeight>0?Math.min(b,f.maxHeight):b,c.height(b)}).one("mouseup",function(){b.off("mousemove")})}},D=function(){var b=new z,c=function(b,c){var d=c&&c.isAirMode,e=c&&c.isLeftTop,f=a(b),g=d?f.offset():f.position(),h=e?0:f.outerHeight(!0);return{left:g.left,top:g.top+h}},d=function(a,b){a.css({display:"block",left:b.left,top:b.top})},e=20;this.update=function(f,g,h){b.update(f,g);var i=f.find(".note-link-popover");if(g.anchor){var l=i.find("a"),m=a(g.anchor).attr("href"),n=a(g.anchor).attr("target");l.attr("href",m).html(m),n?l.attr("target","_blank"):l.removeAttr("target"),d(i,c(g.anchor,{isAirMode:h}))}else i.hide();var o=f.find(".note-image-popover");g.image?d(o,c(g.image,{isAirMode:h,isLeftTop:!0})):o.hide();var p=f.find(".note-air-popover");if(h&&g.range&&!g.range.isCollapsed()){var q=k.last(g.range.getClientRects());if(q){var r=j.rect2bnd(q);d(p,{left:Math.max(r.left+r.width/2-e,0),top:r.top+r.height})}}else p.hide()},this.updateRecentColor=function(a,b,c){a.updateRecentColor(a,b,c)},this.hide=function(a){a.children().hide()}},E=function(b){var c=a(document),d=function(d){if(n.isControlSizing(d.target)){d.preventDefault(),d.stopPropagation();var e=n.makeLayoutInfo(d.target),f=e.handle(),g=e.popover(),h=e.editable(),i=e.editor(),j=f.find(".note-control-selection").data("target"),k=a(j),l=k.offset(),m=c.scrollTop(),o=i.data("options").airMode;c.on("mousemove",function(a){b.invoke("editor.resizeTo",{x:a.clientX-l.left,y:a.clientY-(l.top-m)},k,!a.shiftKey),b.invoke("handle.update",f,{image:j},o),b.invoke("popover.update",g,{image:j},o)}).one("mouseup",function(){c.off("mousemove"),b.invoke("editor.afterCommand",h)}),k.data("ratio")||k.data("ratio",k.height()/k.width())}};this.attach=function(a){a.handle().on("mousedown",d)},this.update=function(b,c,d){var e=b.find(".note-control-selection");if(c.image){var f=a(c.image),g=d?f.offset():f.position(),h={w:f.outerWidth(!0),h:f.outerHeight(!0)};e.css({display:"block",left:g.left,top:g.top,width:h.w,height:h.h}).data("target",c.image);var i=h.w+"x"+h.h;e.find(".note-control-selection-info").text(i)}else e.hide()},this.hide=function(a){a.children().hide()}},F=function(b){var c=a(window),d=a("html, body");this.toggle=function(a){var e=a.editor(),f=a.toolbar(),g=a.editable(),h=a.codable(),i=function(a){g.css("height",a.h),h.css("height",a.h),h.data("cmeditor")&&h.data("cmeditor").setsize(null,a.h)};e.toggleClass("fullscreen");var j=e.hasClass("fullscreen");j?(g.data("orgheight",g.css("height")),c.on("resize",function(){i({h:c.height()-f.outerHeight()})}).trigger("resize"),d.css("overflow","hidden")):(c.off("resize"),i({h:g.data("orgheight")}),d.css("overflow","visible")),b.invoke("toolbar.updateFullscreen",f,j)}};i.hasCodeMirror&&(i.isSupportAmd?require(["CodeMirror"],function(a){h=a}):h=window.CodeMirror);var G=function(a){this.sync=function(b){var c=a.invoke("codeview.isActivated",b);c&&i.hasCodeMirror&&b.codable().data("cmEditor").save()},this.isActivated=function(a){var b=a.editor();return b.hasClass("codeview")},this.toggle=function(a){this.isActivated(a)?this.deactivate(a):this.activate(a)},this.activate=function(b){var c=b.editor(),d=b.toolbar(),e=b.editable(),f=b.codable(),g=b.popover(),j=b.handle(),k=c.data("options");if(f.val(n.html(e,k.prettifyHtml)),f.height(e.height()),a.invoke("toolbar.updateCodeview",d,!0),a.invoke("popover.hide",g),a.invoke("handle.hide",j),c.addClass("codeview"),f.focus(),i.hasCodeMirror){var l=h.fromTextArea(f[0],k.codemirror);if(k.codemirror.tern){var m=new h.TernServer(k.codemirror.tern);l.ternServer=m,l.on("cursorActivity",function(a){m.updateArgHints(a)})}l.setSize(null,e.outerHeight()),f.data("cmEditor",l)}},this.deactivate=function(b){var c=b.holder(),d=b.editor(),e=b.toolbar(),f=b.editable(),g=b.codable(),h=d.data("options");if(i.hasCodeMirror){var j=g.data("cmEditor");g.val(j.getValue()),j.toTextArea()}var k=n.value(g,h.prettifyHtml)||n.emptyPara,l=f.html()!==k;f.html(k),f.height(h.height?g.height():"auto"),d.removeClass("codeview"),l&&a.bindCustomEvent(c,f.data("callbacks"),"change")(f.html(),f),f.focus(),a.invoke("toolbar.updateCodeview",e,!1)}},H=function(b){var c=a(document);this.attach=function(a,b){b.airMode||b.disableDragAndDrop?c.on("drop",function(a){a.preventDefault()}):this.attachDragAndDropEvent(a,b)},this.attachDragAndDropEvent=function(d,e){var f=a(),g=d.editor(),h=d.dropzone(),i=h.find(".note-dropzone-message");c.on("dragenter",function(a){var c=b.invoke("codeview.isActivated",d),j=g.width()>0&&g.height()>0;c||f.length||!j||(g.addClass("dragover"),h.width(g.width()),h.height(g.height()),i.text(e.langInfo.image.dragImageHere)),f=f.add(a.target)}).on("dragleave",function(a){f=f.not(a.target),f.length||g.removeClass("dragover")}).on("drop",function(){f=a(),g.removeClass("dragover")}),h.on("dragenter",function(){h.addClass("hover"),i.text(e.langInfo.image.dropImage)}).on("dragleave",function(){h.removeClass("hover"),i.text(e.langInfo.image.dragImageHere)}),h.on("drop",function(c){var d=c.originalEvent.dataTransfer,e=n.makeLayoutInfo(c.currentTarget||c.target);if(d&&d.files&&d.files.length)c.preventDefault(),e.editable().focus(),b.insertImages(e,d.files);else for(var f=function(){e.holder().summernote("insertNode",this)},g=0,h=d.types.length;h>g;g++){var i=d.types[g],j=d.getData(i);i.toLowerCase().indexOf("text")>-1?e.holder().summernote("pasteHTML",j):a(j).each(f)}}).on("dragover",!1)}},I=function(b){var c;this.attach=function(f){i.isMSIE&&i.browserVersion>10||i.isFF?(c=a("").attr("contenteditable",!0).css({position:"absolute",left:-1e5,opacity:0}),f.editable().on("keydown",function(a){a.ctrlKey&&a.keyCode===r.code.V&&(b.invoke("saveRange",f.editable()),c.focus(),setTimeout(function(){d(f)},0))}),f.editable().before(c)):f.editable().on("paste",e)};var d=function(d){var e=d.editable(),f=c[0].firstChild;if(n.isImg(f)){for(var g=f.src,h=atob(g.split(",")[1]),i=new Uint8Array(h.length),j=0;j").html(c.html()).html();b.invoke("restoreRange",e),b.invoke("focus",e),l&&b.invoke("pasteHTML",e,l)}c.empty()},e=function(a){var c=a.originalEvent.clipboardData,d=n.makeLayoutInfo(a.currentTarget||a.target),e=d.editable();if(c&&c.items&&c.items.length){var f=k.head(c.items);"file"===f.kind&&-1!==f.type.indexOf("image/")&&b.insertImages(d,[f.getAsFile()]),b.invoke("editor.afterCommand",e)}}},J=function(b){var c=function(a,b){a.toggleClass("disabled",!b),a.attr("disabled",!b)},d=function(a,b){a.on("keypress",function(a){a.keyCode===r.code.ENTER&&b.trigger("click")})};this.showLinkDialog=function(b,e,f){return a.Deferred(function(a){var b=e.find(".note-link-dialog"),g=b.find(".note-link-text"),h=b.find(".note-link-url"),i=b.find(".note-link-btn"),j=b.find("input[type=checkbox]");b.one("shown.bs.modal",function(){g.val(f.text),g.on("input",function(){c(i,g.val()&&h.val()),f.text=g.val()}),f.url||(f.url=f.text||"http://",c(i,f.text)),h.on("input",function(){c(i,g.val()&&h.val()),f.text||g.val(h.val())}).val(f.url).trigger("focus").trigger("select"),d(h,i),d(g,i),j.prop("checked",f.isNewWindow),i.one("click",function(c){c.preventDefault(),a.resolve({range:f.range,url:h.val(),text:g.val(),isNewWindow:j.is(":checked")}),b.modal("hide")})}).one("hidden.bs.modal",function(){g.off("input keypress"),h.off("input keypress"),i.off("click"),"pending"===a.state()&&a.reject()}).modal("show")}).promise()},this.show=function(a){var c=a.editor(),d=a.dialog(),e=a.editable(),f=a.popover(),g=b.invoke("editor.getLinkInfo",e),h=c.data("options");b.invoke("editor.saveRange",e),this.showLinkDialog(e,d,g).then(function(a){b.invoke("editor.restoreRange",e),b.invoke("editor.createLink",e,a,h),b.invoke("popover.hide",f)}).fail(function(){b.invoke("editor.restoreRange",e)})}},K=function(b){var c=function(a,b){a.toggleClass("disabled",!b),a.attr("disabled",!b)},d=function(a,b){a.on("keypress",function(a){a.keyCode===r.code.ENTER&&b.trigger("click")})};this.show=function(a){var c=a.dialog(),d=a.editable();b.invoke("editor.saveRange",d),this.showImageDialog(d,c).then(function(c){b.invoke("editor.restoreRange",d),"string"==typeof c?b.invoke("editor.insertImage",d,c):b.insertImages(a,c)}).fail(function(){b.invoke("editor.restoreRange",d)})},this.showImageDialog=function(b,e){return a.Deferred(function(a){var b=e.find(".note-image-dialog"),f=e.find(".note-image-input"),g=e.find(".note-image-url"),h=e.find(".note-image-btn");b.one("shown.bs.modal",function(){f.replaceWith(f.clone().on("change",function(){a.resolve(this.files||this.value),b.modal("hide")}).val("")),h.click(function(c){c.preventDefault(),a.resolve(g.val()),b.modal("hide")}),g.on("keyup paste",function(a){var b;b="paste"===a.type?a.originalEvent.clipboardData.getData("text"):g.val(),c(h,b)}).val("").trigger("focus"),d(g,h)}).one("hidden.bs.modal",function(){f.off("change"),g.off("keyup paste keypress"),h.off("click"),"pending"===a.state()&&a.reject()}).modal("show")})}},L=function(b){this.showHelpDialog=function(b,c){return a.Deferred(function(a){var b=c.find(".note-help-dialog");b.one("hidden.bs.modal",function(){a.resolve()}).modal("show")}).promise()},this.show=function(a){var c=a.dialog(),d=a.editable();b.invoke("editor.saveRange",d,!0),this.showHelpDialog(d,c).then(function(){b.invoke("editor.restoreRange",d)})}},M=function(){var b=this,c=this.modules={editor:new y(this),toolbar:new A(this),statusbar:new C(this),popover:new D(this),handle:new E(this),fullscreen:new F(this),codeview:new G(this),dragAndDrop:new H(this),clipboard:new I(this),linkDialog:new J(this),imageDialog:new K(this),helpDialog:new L(this)};this.invoke=function(){var a=k.head(k.from(arguments)),b=k.tail(k.from(arguments)),c=a.split("."),d=c.length>1,e=d&&k.head(c),f=d?k.last(c):k.head(c),g=this.getModule(e),h=g[f];return h&&h.apply(g,b)},this.getModule=function(a){return this.modules[a]||this.modules.editor};var d=this.bindCustomEvent=function(a,b,c){return function(){var d=b[j.namespaceToCamel(c,"on")];return d&&d.apply(a[0],arguments),a.trigger("summernote."+c,arguments)}};this.insertImages=function(b,e){var f=b.editor(),g=b.editable(),h=b.holder(),i=g.data("callbacks"),j=f.data("options");i.onImageUpload?d(h,i,"image.upload")(e):a.each(e,function(a,b){var e=b.name;j.maximumImageFileSize&&j.maximumImageFileSizej;j++)a.isFunction(a.summernote.plugins[j].init)&&a.summernote.plugins[j].init(b)},this.detach=function(a,b){a.holder().off(),a.editable().off(),a.popover().off(),a.handle().off(),a.dialog().off(),b.airMode||(a.dropzone().off(),a.toolbar().off(),a.statusbar().off())}},N=function(){var b=function(a,b){var c=b.event,d=b.value,e=b.title,f=b.className,g=b.dropdown,h=b.hide;return(g?'':"")+'"+(g||"")+(g?"
":"")},c=function(a,c){var d='';return b(d,c)},d=function(b,c){var d=a('');return d.find(".popover-content").append(c),d},e=function(a,b,c,d){return''+(b?'":"")+'
'+c+"
"+(d?'":"")+"
"},f=function(a,b,c){var d="dropdown-menu"+(b?" "+b:"");return c=c||"ul",a instanceof Array&&(a=a.join("")),"<"+c+' class="'+d+'">'+a+""+c+">"},g={picture:function(a,b){return c(b.iconPrefix+b.icons.image.image,{event:"showImageDialog",title:a.image.image,hide:!0})},link:function(a,b){return c(b.iconPrefix+b.icons.link.link,{event:"showLinkDialog",title:a.link.link,hide:!0})},table:function(a,b){var d=['",' 1 x 1
'];return c(b.iconPrefix+b.icons.table.table,{title:a.table.table,dropdown:f(d,"note-table")})},style:function(a,b){var d=b.styleTags.reduce(function(b,c){var d=a.style["p"===c?"normal":c];return b+''+("p"===c||"pre"===c?d:"<"+c+">"+d+""+c+">")+""},"");return c(b.iconPrefix+b.icons.style.style,{title:a.style.style,dropdown:f(d)})},fontname:function(a,c){var d=[],e=c.fontNames.reduce(function(a,b){return i.isFontInstalled(b)||k.contains(c.fontNamesIgnoreCheck,b)?(d.push(b),a+' '+b+""):a},""),g=i.isFontInstalled(c.defaultFontName),h=g?c.defaultFontName:d[0],j=''+h+"";return b(j,{title:a.font.name,className:"note-fontname",dropdown:f(e,"note-check")})},fontsize:function(a,c){var d=c.fontSizes.reduce(function(a,b){return a+' '+b+""},""),e='11';return b(e,{title:a.font.size,className:"note-fontsize",dropdown:f(d,"note-check")})},color:function(a,c){var d='',e=b(d,{className:"note-recent-color",title:a.color.recent,event:"color",value:'{"backColor":"yellow"}'}),g=['','
'+a.color.background+"
",'
'+a.color.setTransparent+"
",'
','
','
'+a.color.foreground+"
",'
',a.color.resetToDefault,"
",'
',"
"],h=b("",{title:a.color.more,dropdown:f(g)});return e+h},bold:function(a,b){return c(b.iconPrefix+b.icons.font.bold,{event:"bold",title:a.font.bold})},italic:function(a,b){return c(b.iconPrefix+b.icons.font.italic,{event:"italic",title:a.font.italic})},underline:function(a,b){return c(b.iconPrefix+b.icons.font.underline,{event:"underline",title:a.font.underline})},strikethrough:function(a,b){return c(b.iconPrefix+b.icons.font.strikethrough,{event:"strikethrough",title:a.font.strikethrough})},superscript:function(a,b){return c(b.iconPrefix+b.icons.font.superscript,{event:"superscript",title:a.font.superscript})},subscript:function(a,b){return c(b.iconPrefix+b.icons.font.subscript,{event:"subscript",title:a.font.subscript})},clear:function(a,b){return c(b.iconPrefix+b.icons.font.clear,{event:"removeFormat",title:a.font.clear})},ul:function(a,b){return c(b.iconPrefix+b.icons.lists.unordered,{event:"insertUnorderedList",title:a.lists.unordered})},ol:function(a,b){return c(b.iconPrefix+b.icons.lists.ordered,{event:"insertOrderedList",title:a.lists.ordered})},paragraph:function(a,b){var d=c(b.iconPrefix+b.icons.paragraph.left,{title:a.paragraph.left,event:"justifyLeft"}),e=c(b.iconPrefix+b.icons.paragraph.center,{title:a.paragraph.center,event:"justifyCenter"}),g=c(b.iconPrefix+b.icons.paragraph.right,{title:a.paragraph.right,event:"justifyRight"}),h=c(b.iconPrefix+b.icons.paragraph.justify,{title:a.paragraph.justify,event:"justifyFull"}),i=c(b.iconPrefix+b.icons.paragraph.outdent,{title:a.paragraph.outdent,event:"outdent"}),j=c(b.iconPrefix+b.icons.paragraph.indent,{title:a.paragraph.indent,event:"indent"}),k=['',d+e+g+h,'
',j+i,"
"];
+return c(b.iconPrefix+b.icons.paragraph.paragraph,{title:a.paragraph.paragraph,dropdown:f(k,"","div")})},height:function(a,b){var d=b.lineHeights.reduce(function(a,c){return a+' '+c+""},"");return c(b.iconPrefix+b.icons.font.height,{title:a.font.height,dropdown:f(d,"note-check")})},help:function(a,b){return c(b.iconPrefix+b.icons.options.help,{event:"showHelpDialog",title:a.options.help,hide:!0})},fullscreen:function(a,b){return c(b.iconPrefix+b.icons.options.fullscreen,{event:"fullscreen",title:a.options.fullscreen})},codeview:function(a,b){return c(b.iconPrefix+b.icons.options.codeview,{event:"codeview",title:a.options.codeview})},undo:function(a,b){return c(b.iconPrefix+b.icons.history.undo,{event:"undo",title:a.history.undo})},redo:function(a,b){return c(b.iconPrefix+b.icons.history.redo,{event:"redo",title:a.history.redo})},hr:function(a,b){return c(b.iconPrefix+b.icons.hr.insert,{event:"insertHorizontalRule",title:a.hr.insert})}},h=function(e,f){var h=function(){var a=c(f.iconPrefix+f.icons.link.edit,{title:e.link.edit,event:"showLinkDialog",hide:!0}),b=c(f.iconPrefix+f.icons.link.unlink,{title:e.link.unlink,event:"unlink"}),g='www.google.com '+a+b+"
";return d("note-link-popover",g)},i=function(){var a=b('100%',{title:e.image.resizeFull,event:"resize",value:"1"}),g=b('50%',{title:e.image.resizeHalf,event:"resize",value:"0.5"}),h=b('25%',{title:e.image.resizeQuarter,event:"resize",value:"0.25"}),i=c(f.iconPrefix+f.icons.image.floatLeft,{title:e.image.floatLeft,event:"floatMe",value:"left"}),j=c(f.iconPrefix+f.icons.image.floatRight,{title:e.image.floatRight,event:"floatMe",value:"right"}),k=c(f.iconPrefix+f.icons.image.floatNone,{title:e.image.floatNone,event:"floatMe",value:"none"}),l=c(f.iconPrefix+f.icons.image.shapeRounded,{title:e.image.shapeRounded,event:"imageShape",value:"img-rounded"}),m=c(f.iconPrefix+f.icons.image.shapeCircle,{title:e.image.shapeCircle,event:"imageShape",value:"img-circle"}),n=c(f.iconPrefix+f.icons.image.shapeThumbnail,{title:e.image.shapeThumbnail,event:"imageShape",value:"img-thumbnail"}),o=c(f.iconPrefix+f.icons.image.shapeNone,{title:e.image.shapeNone,event:"imageShape",value:""}),p=c(f.iconPrefix+f.icons.image.remove,{title:e.image.remove,event:"removeMedia",value:"none"}),q=(f.disableResizeImage?"":''+a+g+h+"
")+''+i+j+k+'
'+l+m+n+o+'
'+p+"
";return d("note-image-popover",q)},j=function(){for(var b=a(""),c=0,h=f.airPopover.length;h>c;c++){for(var i=f.airPopover[c],j=a(''),k=0,l=i[1].length;l>k;k++){var m=a(g[i[1][k]](e,f));m.attr("data-name",i[1][k]),j.append(m)}b.append(j)}return d("note-air-popover",b.children())},k=a('
');return k.append(h()),k.append(i()),f.airMode&&k.append(j()),k},l=function(a){return'
'+(a.disableResizeImage?"":'
')+"
"},m=function(a,b){var c="note-shortcut-col col-xs-6 note-shortcut-",d=[];for(var e in b)b.hasOwnProperty(e)&&d.push('
'+b[e].kbd+'
'+b[e].text+"
");return'
'+d.join('
')+"
"},o=function(a){var b=[{kbd:"⌘ + B",text:a.font.bold},{kbd:"⌘ + I",text:a.font.italic},{kbd:"⌘ + U",text:a.font.underline},{kbd:"⌘ + \\",text:a.font.clear}];return m(a.shortcut.textFormatting,b)},p=function(a){var b=[{kbd:"⌘ + Z",text:a.history.undo},{kbd:"⌘ + ⇧ + Z",text:a.history.redo},{kbd:"⌘ + ]",text:a.paragraph.indent},{kbd:"⌘ + [",text:a.paragraph.outdent},{kbd:"⌘ + ENTER",text:a.hr.insert}];return m(a.shortcut.action,b)},q=function(a){var b=[{kbd:"⌘ + ⇧ + L",text:a.paragraph.left},{kbd:"⌘ + ⇧ + E",text:a.paragraph.center},{kbd:"⌘ + ⇧ + R",text:a.paragraph.right},{kbd:"⌘ + ⇧ + J",text:a.paragraph.justify},{kbd:"⌘ + ⇧ + NUM7",text:a.lists.ordered},{kbd:"⌘ + ⇧ + NUM8",text:a.lists.unordered}];return m(a.shortcut.paragraphFormatting,b)},r=function(a){var b=[{kbd:"⌘ + NUM0",text:a.style.normal},{kbd:"⌘ + NUM1",text:a.style.h1},{kbd:"⌘ + NUM2",text:a.style.h2},{kbd:"⌘ + NUM3",text:a.style.h3},{kbd:"⌘ + NUM4",text:a.style.h4},{kbd:"⌘ + NUM5",text:a.style.h5},{kbd:"⌘ + NUM6",text:a.style.h6}];return m(a.shortcut.documentStyle,b)},s=function(a,b){var c=b.extraKeys,d=[];for(var e in c)c.hasOwnProperty(e)&&d.push({kbd:e,text:c[e]});return m(a.shortcut.extraKeys,d)},t=function(a,b){var c='class="note-shortcut note-shortcut-col col-sm-6 col-xs-12"',d=["
"+p(a,b)+"
"+o(a,b)+"
","
"+r(a,b)+"
"+q(a,b)+"
"];return b.extraKeys&&d.push("
"+s(a,b)+"
"),'
'+d.join('
')+"
"},u=function(a){return a.replace(/⌘/g,"Ctrl").replace(/⇧/g,"Shift")},v={image:function(a,b){var c="";if(b.maximumImageFileSize){var d=Math.floor(Math.log(b.maximumImageFileSize)/Math.log(1024)),f=1*(b.maximumImageFileSize/Math.pow(1024,d)).toFixed(2)+" "+" KMGTP"[d]+"B";c="
"+a.image.maximumFileSize+" : "+f+""}var g='
'+c+'
',h='
";return e("note-image-dialog",a.image.insert,g,h)},link:function(a,b){var c='
'+(b.disableLinkTarget?"":'
"),d='
";return e("note-link-dialog",a.link.insert,c,d)},help:function(a,b){var c='
'+a.shortcut.close+''+a.shortcut.shortcuts+"
"+(i.isMac?t(a,b):u(t(a,b)))+'
Summernote 0.6.16 · Project · Issues
';return e("note-help-dialog","",c,"")}},w=function(b,c){var d="";return a.each(v,function(a,e){d+=e(b,c)}),'
'+d+"
"},x=function(){return'
'},y=function(a){return i.isMac&&(a=a.replace("CMD","⌘").replace("SHIFT","⇧")),a.replace("BACKSLASH","\\").replace("SLASH","/").replace("LEFTBRACKET","[").replace("RIGHTBRACKET","]")},z=function(b,c,d){var e=j.invertObject(c),f=b.find("button");f.each(function(b,c){var d=a(c),f=e[d.data("event")];f&&d.attr("title",function(a,b){return b+" ("+y(f)+")"})}).tooltip({container:"body",trigger:"hover",placement:d||"top"}).on("click",function(){a(this).tooltip("hide")})},A=function(b,c){var d=c.colors;b.find(".note-color-palette").each(function(){for(var b=a(this),c=b.attr("data-target-event"),e=[],f=0,g=d.length;g>f;f++){for(var h=d[f],i=[],j=0,k=h.length;k>j;j++){var l=h[j];i.push(['
'].join(""))}e.push('
'+i.join("")+"
")}b.html(e.join(""))})};this.createLayoutByAirMode=function(b,c){var d=c.langInfo,e=c.keyMap[i.isMac?"mac":"pc"],f=j.uniqueId();b.addClass("note-air-editor note-editable panel-body"),b.attr({id:"note-editor-"+f,contentEditable:!0});var g=document.body,k=a(h(d,c));k.addClass("note-air-layout"),k.attr("id","note-popover-"+f),k.appendTo(g),z(k,e),A(k,c);var m=a(l(c));m.addClass("note-air-layout"),m.attr("id","note-handle-"+f),m.appendTo(g);var n=a(w(d,c));n.addClass("note-air-layout"),n.attr("id","note-dialog-"+f),n.find("button.close, a.modal-close").click(function(){a(this).closest(".modal").modal("hide")}),n.appendTo(g)},this.createLayoutByFrame=function(b,c){var d=c.langInfo,e=a('
');c.width&&e.width(c.width),c.height>0&&a('
'+(c.disableResizeEditor?"":x())+"
").prependTo(e);var f=a('
'),j=!b.is(":disabled"),k=a('
').prependTo(f);c.height&&k.height(c.height),c.direction&&k.attr("dir",c.direction);var m=b.attr("placeholder")||c.placeholder;m&&k.attr("data-placeholder",m),k.html(n.html(b)||n.emptyPara),a('
').prependTo(f);var o=a(h(d,c)).prependTo(f);A(o,c),z(o,D),a(l(c)).prependTo(f),f.prependTo(e);for(var p=a('
'),q=0,r=c.toolbar.length;r>q;q++){for(var s=c.toolbar[q][0],t=c.toolbar[q][1],u=a('
'),v=0,y=t.length;y>v;v++){var B=g[t[v]];if(a.isFunction(B)){var C=a(B(d,c));C.attr("data-name",t[v]),u.append(C)}}p.append(u)}var D=c.keyMap[i.isMac?"mac":"pc"];A(p,c),z(p,D,"bottom"),p.prependTo(e),a('
').prependTo(e);var E=c.dialogsInBody?a(document.body):e,F=a(w(d,c)).prependTo(E);F.find("button.close, a.modal-close").click(function(){a(this).closest(".modal").modal("hide")}),e.insertAfter(b),b.hide()},this.hasNoteEditor=function(a){return this.noteEditorFromHolder(a).length>0},this.noteEditorFromHolder=function(b){return b.hasClass("note-air-editor")?b:b.next().hasClass("note-editor")?b.next():a()},this.createLayout=function(a,b){b.airMode?this.createLayoutByAirMode(a,b):this.createLayoutByFrame(a,b)},this.layoutInfoFromHolder=function(a){var b=this.noteEditorFromHolder(a);if(b.length)return b.data("holder",a),n.buildLayoutInfo(b)},this.removeLayout=function(a,b,c){c.airMode?(a.removeClass("note-air-editor note-editable").removeAttr("id contentEditable"),b.popover().remove(),b.handle().remove(),b.dialog().remove()):(a.html(b.editable().html()),c.dialogsInBody&&b.dialog().remove(),b.editor().remove(),a.show())},this.getTemplate=function(){return{button:b,iconButton:c,dialog:e}},this.addButtonInfo=function(a,b){g[a]=b},this.addDialogInfo=function(a,b){v[a]=b}};a.summernote=a.summernote||{},a.extend(a.summernote,p);var O=new N,P=new M;a.extend(a.summernote,{renderer:O,eventHandler:P,core:{agent:i,list:k,dom:n,range:o},pluginEvents:{},plugins:[]}),a.summernote.addPlugin=function(b){a.summernote.plugins.push(b),b.buttons&&a.each(b.buttons,function(a,b){O.addButtonInfo(a,b)}),b.dialogs&&a.each(b.dialogs,function(a,b){O.addDialogInfo(a,b)}),b.events&&a.each(b.events,function(b,c){a.summernote.pluginEvents[b]=c}),b.langs&&a.each(b.langs,function(b,c){a.summernote.lang[b]&&a.extend(a.summernote.lang[b],c)}),b.options&&a.extend(a.summernote.options,b.options)},a.fn.extend({summernote:function(){var b=a.type(k.head(arguments)),c="string"===b,d="object"===b,e=d?k.head(arguments):{};if(e=a.extend({},a.summernote.options,e),e.icons=a.extend({},a.summernote.options.icons,e.icons),e.langInfo=a.extend(!0,{},a.summernote.lang["en-US"],a.summernote.lang[e.lang]),!c&&d)for(var f=0,g=a.summernote.plugins.length;g>f;f++){var h=a.summernote.plugins[f];e.plugin[h.name]&&(a.summernote.plugins[f]=a.extend(!0,h,e.plugin[h.name]))}this.each(function(b,c){var d=a(c);if(!O.hasNoteEditor(d)){O.createLayout(d,e);var f=O.layoutInfoFromHolder(d);d.data("layoutInfo",f),P.attach(f,e),P.attachCustomEvent(f,e)}});var i=this.first();if(i.length){var j=O.layoutInfoFromHolder(i);if(c){var l=k.head(k.from(arguments)),m=k.tail(k.from(arguments)),n=[l,j.editable()].concat(m);return P.invoke.apply(P,n)}e.focus&&j.editable().focus()}return this},code:function(b){if(void 0===b){var c=this.first();if(!c.length)return;var d=O.layoutInfoFromHolder(c),e=d&&d.editable();if(e&&e.length){var f=P.invoke("codeview.isActivated",d);return P.invoke("codeview.sync",d),f?d.codable().val():d.editable().html()}return n.value(c)}return this.each(function(c,d){var e=O.layoutInfoFromHolder(a(d)),f=e&&e.editable();f&&f.html(b)}),this},destroy:function(){return this.each(function(b,c){var d=a(c);if(O.hasNoteEditor(d)){var e=O.layoutInfoFromHolder(d),f=e.editor().data("options");P.detach(e,f),O.removeLayout(d,e,f)}}),this}})});
\ No newline at end of file
diff --git a/chat.php b/chat.php
index 0617fcf07..8ccd48d8b 100644
--- a/chat.php
+++ b/chat.php
@@ -117,13 +117,7 @@
-webkit-filter: grayscale; /*sepia, hue-rotate, invert....*/
-webkit-filter: brightness(25%);
}
-
+
diff --git a/config/configDefaults.php b/config/configDefaults.php
index d2393ab15..c60f2d00b 100644
--- a/config/configDefaults.php
+++ b/config/configDefaults.php
@@ -9,15 +9,21 @@
"plexRecentTV" => "false",
"plexRecentMusic" => "false",
"plexPlayingNow" => "false",
- "plexShowNames" => false,
+ "plexShowNames" => false,
"plexHomeAuth" => false,
+ "plexSearch" => false,
+ "plexRecentItems" => "20",
+ "plexTabName" => "",
"embyURL" => "",
"embyToken" => "",
"embyRecentMovie" => "false",
"embyRecentTV" => "false",
"embyRecentMusic" => "false",
"embyPlayingNow" => "false",
+ "embyShowNames" => false,
"embyHomeAuth" => false,
+ "embySearch" => false,
+ "embyRecentItems" => "20",
"sonarrURL" => "",
"sonarrKey" => "",
"sonarrHomeAuth" => false,
@@ -72,11 +78,11 @@
"homepageCustomHTML1Auth" => false,
"git_branch" => "master",
"git_check" => true,
- "speedTest" => false,
- "smtpHostType" => "tls",
- "homepageNoticeTitle" => "",
- "homepageNoticeMessage" => "",
- "homepageNoticeType" => "success",
- "homepageNoticeAuth" => "false",
- "homepageNoticeLayout" => "elegant",
+ "speedTest" => false,
+ "smtpHostType" => "tls",
+ "homepageNoticeTitle" => "",
+ "homepageNoticeMessage" => "",
+ "homepageNoticeType" => "success",
+ "homepageNoticeAuth" => "false",
+ "homepageNoticeLayout" => "elegant",
);
diff --git a/error.php b/error.php
index 64a561388..0656a5b1a 100755
--- a/error.php
+++ b/error.php
@@ -67,6 +67,7 @@
+
@@ -82,7 +83,7 @@
-
+
diff --git a/functions.php b/functions.php
index 280f9e7df..9b53800a8 100755
--- a/functions.php
+++ b/functions.php
@@ -2,7 +2,7 @@
// ===================================
// Define Version
- define('INSTALLEDVERSION', '1.38');
+ define('INSTALLEDVERSION', '1.40');
// ===================================
// Debugging output functions
@@ -31,13 +31,13 @@ function plugin_auth_ldap($username, $password) {
// returns true or false
$ldap = ldap_connect(implode(' ',$ldapServers));
if ($bind = ldap_bind($ldap, AUTHBACKENDDOMAIN.'\\'.$username, $password)) {
- writeLog("success", "LDAP authentication success");
+ writeLog("success", "LDAP authentication success");
return true;
} else {
- writeLog("error", "LDPA could not authenticate");
+ writeLog("error", "LDPA could not authenticate");
return false;
}
- writeLog("error", "LDPA could not authenticate");
+ writeLog("error", "LDPA could not authenticate");
return false;
}
else :
@@ -62,7 +62,7 @@ function plugin_auth_ftp($username, $password) {
$conn_id = ftp_connect($host, $port, 20);
} else {
debug_out('Invalid FTP scheme. Use ftp or ftps');
- writeLog("error", "invalid FTP scheme");
+ writeLog("error", "invalid FTP scheme");
return false;
}
@@ -74,10 +74,10 @@ function plugin_auth_ftp($username, $password) {
// Return Result
if ($login_result) {
- writeLog("success", "$username authenticated");
+ writeLog("success", "$username authenticated");
return true;
} else {
- writeLog("error", "$username could not authenticate");
+ writeLog("error", "$username could not authenticate");
return false;
}
} else {
@@ -177,7 +177,7 @@ function plugin_auth_emby_connect($username, $password) {
function plugin_auth_plex($username, $password) {
// Quick out
if ((strtolower(PLEXUSERNAME) == strtolower($username)) && $password == PLEXPASSWORD) {
- writeLog("success", $username." authenticated by plex");
+ writeLog("success", $username." authenticated by plex");
return true;
}
@@ -194,7 +194,7 @@ function plugin_auth_plex($username, $password) {
foreach($userXML AS $child) {
if(isset($child['username']) && strtolower($child['username']) == $usernameLower) {
$isUser = true;
- writeLog("success", $usernameLower." was found in plex friends list");
+ writeLog("success", $usernameLower." was found in plex friends list");
break;
}
}
@@ -217,16 +217,19 @@ function plugin_auth_plex($username, $password) {
if (isset($result['content'])) {
$json = json_decode($result['content'], true);
if (is_array($json) && isset($json['user']) && isset($json['user']['username']) && strtolower($json['user']['username']) == $usernameLower) {
- writeLog("success", $json['user']['username']." was logged into plex and pulled credentials");
+ writeLog("success", $json['user']['username']." was logged into organizr using plex credentials");
return array(
'email' => $json['user']['email'],
'image' => $json['user']['thumb']
);
}
}
+ }else{
+ writeLog("error", "$username is not an authorized user or entered invalid password");
}
+ }else{
+ writeLog("error", "error occured logging into plex might want to check curl.cainfo=/path/to/downloaded/cacert.pem in php.ini");
}
- writeLog("error", "error occured logging into plex might want to check curl.cainfo=/path/to/downloaded/cacert.pem in php.ini");
return false;
}
else :
@@ -249,22 +252,28 @@ function plugin_auth_emby_both_disabled() {
// ==== General Class Definitions START ====
class setLanguage {
private $language = null;
- private $langCode = null;
-
- function __construct($language = false) {
- // Default
- if (!$language) {
- $language = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) : "en";
- }
-
- $this->langCode = $language;
-
- if (file_exists("lang/{$language}.ini")) {
- $this->language = parse_ini_file("lang/{$language}.ini", false, INI_SCANNER_RAW);
- } else {
- $this->language = parse_ini_file("lang/en.ini", false, INI_SCANNER_RAW);
+ private $langCode = null;
+
+ function __construct($language = false) {
+ // Default
+ if (!$language) {
+ $language = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) : "en";
+ }
+
+ if (!file_exists("lang/{$language}.ini")) {
+ $language = 'en';
+ }
+
+ $this->langCode = $language;
+
+ $this->language = parse_ini_file("lang/{$language}.ini", false, INI_SCANNER_RAW);
+ if (file_exists("lang/{$language}.cust.ini")) {
+ foreach($tmp = parse_ini_file("lang/{$language}.cust.ini", false, INI_SCANNER_RAW) as $k => $v) {
+ $this->language[$k] = $v;
+ }
}
}
+
public function getLang() {
return $this->langCode;
@@ -309,6 +318,7 @@ function curl_post($url, $data, $headers = array(), $referer='') {
// As post request
curl_setopt($curlReq, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curlReq, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curlReq, CURLOPT_CAINFO, getCert());
// Format Data
switch (isset($headers['Content-Type'])?$headers['Content-Type']:'') {
case 'application/json':
@@ -331,10 +341,11 @@ function curl_post($url, $data, $headers = array(), $referer='') {
}
// Execute
$result = curl_exec($curlReq);
+ $httpcode = curl_getinfo($curlReq);
// Close
curl_close($curlReq);
// Return
- return array('content'=>$result);
+ return array('content'=>$result, 'http_code'=>$httpcode);
}
//Curl Get Function
@@ -344,6 +355,8 @@ function curl_get($url, $headers = array()) {
// As post request
curl_setopt($curlReq, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($curlReq, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curlReq, CURLOPT_CAINFO, getCert());
+ curl_setopt($curlReq, CURLOPT_CONNECTTIMEOUT, 5);
// Format Headers
$cHeaders = array();
foreach ($headers as $k => $v) {
@@ -359,6 +372,32 @@ function curl_get($url, $headers = array()) {
// Return
return $result;
}
+
+ //Curl Delete Function
+ function curl_delete($url, $headers = array()) {
+ // Initiate cURL
+ $curlReq = curl_init($url);
+ // As post request
+ curl_setopt($curlReq, CURLOPT_CUSTOMREQUEST, "DELETE");
+ curl_setopt($curlReq, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curlReq, CURLOPT_CONNECTTIMEOUT, 5);
+ curl_setopt($curlReq, CURLOPT_CAINFO, getCert());
+ // Format Headers
+ $cHeaders = array();
+ foreach ($headers as $k => $v) {
+ $cHeaders[] = $k.': '.$v;
+ }
+ if (count($cHeaders)) {
+ curl_setopt($curlReq, CURLOPT_HTTPHEADER, $cHeaders);
+ }
+ // Execute
+ $result = curl_exec($curlReq);
+ $httpcode = curl_getinfo($curlReq);
+ // Close
+ curl_close($curlReq);
+ // Return
+ return array('content'=>$result, 'http_code'=>$httpcode);
+ }
endif;
//Case-Insensitive Function
@@ -446,54 +485,191 @@ function post_request($url, $data, $headers = array(), $referer='') {
}
// Format item from Emby for Carousel
-function resolveEmbyItem($address, $token, $item) {
+function resolveEmbyItem($address, $token, $item, $nowPlaying = false, $showNames = false, $role = false, $moreInfo = false) {
// Static Height
- $height = 150;
+ $height = 444;
// Get Item Details
- $itemDetails = json_decode(file_get_contents($address.'/Items?Ids='.$item['Id'].'&Fields=Overview&api_key='.$token),true)['Items'][0];
-
+ $itemDetails = json_decode(file_get_contents($address.'/Items?Ids='.$item['Id'].'&api_key='.$token),true)['Items'][0];
+ if (substr_count(EMBYURL, ':') == 2) {
+ $URL = "http://app.emby.media/itemdetails.html?id=".$itemDetails['Id'];
+ }else{
+ $URL = EMBYURL."/web/itemdetails.html?id=".$itemDetails['Id'];
+ }
+ //$URL = "http://app.emby.media/itemdetails.html?id=".$itemDetails['Id'];
switch ($itemDetails['Type']) {
- case 'Episode':
- $title = (isset($itemDetails['SeriesName'])?$itemDetails['SeriesName'].': ':'').$itemDetails['Name'].(isset($itemDetails['ParentIndexNumber']) && isset($itemDetails['IndexNumber'])?' (Season '.$itemDetails['ParentIndexNumber'].': Episode '.$itemDetails['IndexNumber'].')':'');
- $imageId = (isset($itemDetails['SeriesId'])?$itemDetails['SeriesId']:$itemDetails['Id']);
- $width = 100;
- $image = 'carousel-image season';
- $style = '';
- break;
+ case 'Episode':
+ $title = (isset($itemDetails['SeriesName'])?$itemDetails['SeriesName']:"");
+ $imageId = (isset($itemDetails['SeriesId'])?$itemDetails['SeriesId']:$itemDetails['Id']);
+ $width = 300;
+ $style = '';
+ $image = 'slick-image-tall';
+ if(!$nowPlaying){
+ $imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
+ $key = $itemDetails['Id'] . "-list";
+ }else{
+ $height = 281;
+ $width = 500;
+ $imageId = isset($itemDetails['ParentThumbItemId']) ? $itemDetails['ParentThumbItemId'] : (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : false);
+ $imageType = isset($itemDetails['ParentThumbItemId']) ? "Thumb" : (isset($itemDetails['ParentBackdropItemId']) ? "Backdrop" : false);
+ $key = (isset($itemDetails['ParentThumbItemId']) ? $itemDetails['ParentThumbItemId']."-np" : "none-np");
+ $elapsed = $moreInfo['PlayState']['PositionTicks'];
+ $duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
+ $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
+ //$transcoded = floor($item->TranscodeSession['progress']- $watched);
+ $stream = $moreInfo['PlayState']['PlayMethod'];
+ $user = $role == "admin" ? $moreInfo['UserName'] : "";
+ $id = $moreInfo['DeviceId'];
+ $streamInfo = buildStream(array(
+ 'platform' => (string) $moreInfo['Client'],
+ 'device' => (string) $moreInfo['DeviceName'],
+ 'stream' => " ".streamType($stream),
+ 'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
+ 'audio' => " ".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
+ ));
+ $state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
+ $topTitle = ''.$title.' - '.$itemDetails['Name'].'
';
+ $bottomTitle = 'S'.$itemDetails['ParentIndexNumber'].' · E'.$itemDetails['IndexNumber'].'';
+ if($showNames == "true"){ $bottomTitle .= ''.$user.''; }
+ }
+ break;
case 'MusicAlbum':
+ case 'Audio':
$title = $itemDetails['Name'];
$imageId = $itemDetails['Id'];
- $width = 150;
- $image = 'music';
- $style = 'left: 160px !important;';
+ $width = 444;
+ $style = '';
+ $image = 'slick-image-short';
+ if(!$nowPlaying){
+ $imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
+ $key = $itemDetails['Id'] . "-list";
+ }else{
+ $height = 281;
+ $width = 500;
+ $imageId = (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : false);
+ $imageType = (isset($itemDetails['ParentBackdropItemId']) ? "Backdrop" : false);
+ $key = (isset($itemDetails['ParentBackdropItemId']) ? $itemDetails['ParentBackdropItemId'] : "no-np") . "-np";
+ $elapsed = $moreInfo['PlayState']['PositionTicks'];
+ $duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
+ $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
+ //$transcoded = floor($item->TranscodeSession['progress']- $watched);
+ $stream = $moreInfo['PlayState']['PlayMethod'];
+ $user = $role == "admin" ? $moreInfo['UserName'] : "";
+ $id = $moreInfo['DeviceId'];
+ $streamInfo = buildStream(array(
+ 'platform' => (string) $moreInfo['Client'],
+ 'device' => (string) $moreInfo['DeviceName'],
+ 'stream' => " ".streamType($stream),
+ 'audio' => " ".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
+ ));
+ $state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
+ $topTitle = ''.$itemDetails['AlbumArtist'].' - '.$itemDetails['Album'].'
';
+ $bottomTitle = ''.$title.'';
+ if($showNames == "true"){ $bottomTitle .= ''.$user.''; }
+ }
break;
+ case 'TvChannel':
+ $title = $itemDetails['CurrentProgram']['Name'];
+ $imageId = $itemDetails['Id'];
+ $width = 300;
+ $style = '';
+ $image = 'slick-image-tall';
+ if(!$nowPlaying){
+ $imageType = "Primary";
+ $key = $itemDetails['Id'] . "-list";
+ }else{
+ $height = 281;
+ $width = 500;
+ $imageType = "Thumb";
+ $key = $itemDetails['Id'] . "-np";
+ $useImage = "images/livetv.png";
+ $watched = "0";
+ $stream = $moreInfo['PlayState']['PlayMethod'];
+ $user = $role == "admin" ? $moreInfo['UserName'] : "";
+ $id = $moreInfo['DeviceId'];
+ $streamInfo = buildStream(array(
+ 'platform' => (string) $moreInfo['Client'],
+ 'device' => (string) $moreInfo['DeviceName'],
+ 'stream' => " ".streamType($stream),
+ 'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
+ 'audio' => " ".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
+ ));
+ $state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
+ $topTitle = ''.$title.'
';
+ $bottomTitle = ''.$itemDetails['Name'].' - '.$itemDetails['ChannelNumber'].'';
+ if($showNames == "true"){ $bottomTitle .= ''.$user.''; }
+ }
+ break;
default:
$title = $itemDetails['Name'];
$imageId = $itemDetails['Id'];
- $width = 100;
- $image = 'carousel-image movie';
- $style = '';
+ $width = 300;
+ $style = '';
+ $image = 'slick-image-tall';
+ if(!$nowPlaying){
+ $imageType = (isset($itemDetails['ImageTags']['Primary']) ? "Primary" : false);
+ $key = $itemDetails['Id'] . "-list";
+ }else{
+ $height = 281;
+ $width = 500;
+ $imageType = isset($itemDetails['ImageTags']['Thumb']) ? "Thumb" : (isset($itemDetails['BackdropImageTags']) ? "Backdrop" : false);
+ $key = $itemDetails['Id'] . "-np";
+ $elapsed = $moreInfo['PlayState']['PositionTicks'];
+ $duration = $moreInfo['NowPlayingItem']['RunTimeTicks'];
+ $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
+ //$transcoded = floor($item->TranscodeSession['progress']- $watched);
+ $stream = $moreInfo['PlayState']['PlayMethod'];
+ $user = $role == "admin" ? $moreInfo['UserName'] : "";
+ $id = $moreInfo['DeviceId'];
+ $streamInfo = buildStream(array(
+ 'platform' => (string) $moreInfo['Client'],
+ 'device' => (string) $moreInfo['DeviceName'],
+ 'stream' => " ".streamType($stream),
+ 'video' => streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "video"),
+ 'audio' => " ".streamType($stream)." ".embyArray($moreInfo['NowPlayingItem']['MediaStreams'], "audio"),
+ ));
+ $state = (($moreInfo['PlayState']['IsPaused'] == "1") ? "pause" : "play");
+ $topTitle = ''.$title.'
';
+ $bottomTitle = ''.$moreInfo['NowPlayingItem']['ProductionYear'].'';
+ if($showNames == "true"){ $bottomTitle .= ''.$user.''; }
+ }
}
// If No Overview
if (!isset($itemDetails['Overview'])) {
$itemDetails['Overview'] = '';
}
+
+if (file_exists('images/cache/'.$key.'.jpg')){ $image_url = 'images/cache/'.$key.'.jpg'; }
+ if (file_exists('images/cache/'.$key.'.jpg') && (time() - 604800) > filemtime('images/cache/'.$key.'.jpg') || !file_exists('images/cache/'.$key.'.jpg')) {
+ $image_url = 'ajax.php?a=emby-image&type='.$imageType.'&img='.$imageId.'&height='.$height.'&width='.$width.'&key='.$key.'';
+ }
+
+ if($nowPlaying){
+ if(!$imageType){ $image_url = "images/no-np.png"; $key = "no-np"; }
+ if(!$imageId){ $image_url = "images/no-np.png"; $key = "no-np"; }
+ }else{
+ if(!$imageType){ $image_url = "images/no-list.png"; $key = "no-list"; }
+ if(!$imageId){ $image_url = "images/no-list.png"; $key = "no-list"; }
+ }
+ if(isset($useImage)){ $image_url = $useImage; }
- // Assemble Item And Cache Into Array
- return ''.$title.'
'.$itemDetails['Overview'].' ';
+ // Assemble Item And Cache Into Array
+if($nowPlaying){
+ //prettyPrint($itemDetails);
+ return '';
+ }else{
+ return ''.$title.' ';
+}
}
// Format item from Plex for Carousel
function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames = false, $role = false) {
// Static Height
- $height = 444;
-
- $address = "https://app.plex.tv/web/app#!/server/$server/details?key=/library/metadata/".$item['ratingKey'];
+ $height = 444;
switch ($item['type']) {
- case 'season':
+ case 'season':
$title = $item['parentTitle'];
$summary = $item['parentSummary'];
$width = 300;
@@ -509,11 +685,11 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
$key = $item['ratingKey'] . "-np";
$elapsed = $item['viewOffset'];
$duration = $item['duration'];
- $watched = floor(($elapsed / $duration) * 100);
+ $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
$transcoded = floor($item->TranscodeSession['progress']- $watched);
$stream = $item->Media->Part->Stream['decision'];
$user = $role == "admin" ? $item->User['title'] : "";
- $id = $item->Session['id'];
+ $id = str_replace('"', '', $item->Player['machineIdentifier']);
$streamInfo = buildStream(array(
'platform' => (string) $item->Player['platform'],
'device' => (string) $item->Player['device'],
@@ -540,11 +716,11 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
$key = $item['ratingKey'] . "-np";
$elapsed = $item['viewOffset'];
$duration = $item['duration'];
- $watched = floor(($elapsed / $duration) * 100);
+ $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
$transcoded = floor($item->TranscodeSession['progress']- $watched);
$stream = $item->Media->Part->Stream['decision'];
$user = $role == "admin" ? $item->User['title'] : "";
- $id = $item->Session['id'];
+ $id = str_replace('"', '', $item->Player['machineIdentifier']);
$streamInfo = buildStream(array(
'platform' => (string) $item->Player['platform'],
'device' => (string) $item->Player['device'],
@@ -572,13 +748,14 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
$width = 500;
$thumb = $item['art'];
$key = $item['ratingKey'] . "-np";
+ $extraInfo = isset($item['extraType']) ? "Trailer" : (isset($item['live']) ? "Live TV" : ":)");
$elapsed = $item['viewOffset'];
$duration = $item['duration'];
- $watched = floor(($elapsed / $duration) * 100);
+ $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
$transcoded = floor($item->TranscodeSession['progress']- $watched);
$stream = $item->Media->Part->Stream['decision'];
$user = $role == "admin" ? $item->User['title'] : "";
- $id = $item->Session['id'];
+ $id = str_replace('"', '', $item->Player['machineIdentifier']);
$streamInfo = buildStream(array(
'platform' => (string) $item->Player['platform'],
'device' => (string) $item->Player['device'],
@@ -587,8 +764,8 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
'audio' => " ".streamType($item->Media->Part->Stream[1]['decision'])." (".$item->Media->Part->Stream[1]['codec'].") (".$item->Media->Part->Stream[1]['channels']."ch)",
));
$state = (($item->Player['state'] == "paused") ? "pause" : "play");
- $topTitle = ''.$title.' [Trailer/Clip]
';
- $bottomTitle = ''.$item['year'].'';
+ $topTitle = ''.$title.'
';
+ $bottomTitle = ''.$extraInfo.'';
if($showNames == "true"){ $bottomTitle .= ''.$user.''; }
}
break;
@@ -598,6 +775,7 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
$summary = $item['title'];
$image = 'slick-image-short';
$style = 'left: 160px !important;';
+ $item['ratingKey'] = $item['parentRatingKey'];
if(!$nowPlaying){
$width = 444;
$thumb = $item['thumb'];
@@ -609,16 +787,16 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
$key = $item['ratingKey'] . "-np";
$elapsed = $item['viewOffset'];
$duration = $item['duration'];
- $watched = floor(($elapsed / $duration) * 100);
+ $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
$transcoded = floor($item->TranscodeSession['progress']- $watched);
$stream = $item->Media->Part->Stream['decision'];
$user = $role == "admin" ? $item->User['title'] : "";
- $id = $item->Session['id'];
+ $id = str_replace('"', '', $item->Player['machineIdentifier']);
$streamInfo = buildStream(array(
'platform' => (string) $item->Player['platform'],
'device' => (string) $item->Player['device'],
'stream' => " ".streamType($item->Media->Part['decision']),
- 'audio' => " ".streamType($item->Media->Part->Stream[1]['decision'])." (".$item->Media->Part->Stream[0]['codec'].") (".$item->Media->Part->Stream[0]['channels']."ch)",
+ 'audio' => " ".streamType($item->Media->Part->Stream[0]['decision'])." (".$item->Media->Part->Stream[0]['codec'].") (".$item->Media->Part->Stream[0]['channels']."ch)",
));
$state = (($item->Player['state'] == "paused") ? "pause" : "play");
$topTitle = ''.$item['grandparentTitle'].' - '.$item['title'].'
';
@@ -642,11 +820,11 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
$key = $item['ratingKey'] . "-np";
$elapsed = $item['viewOffset'];
$duration = $item['duration'];
- $watched = floor(($elapsed / $duration) * 100);
+ $watched = (!empty($elapsed) ? floor(($elapsed / $duration) * 100) : 0);
$transcoded = floor($item->TranscodeSession['progress']- $watched);
$stream = $item->Media->Part->Stream['decision'];
$user = $role == "admin" ? $item->User['title'] : "";
- $id = $item->Session['id'];
+ $id = str_replace('"', '', $item->Player['machineIdentifier']);
$streamInfo = buildStream(array(
'platform' => (string) $item->Player['platform'],
'device' => (string) $item->Player['device'],
@@ -659,7 +837,13 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
$bottomTitle = ''.$item['year'].'';
if($showNames == "true"){ $bottomTitle .= ''.$user.''; }
}
- }
+ }
+
+ if (substr_count(PLEXURL, ':') == 2) {
+ $address = "https://app.plex.tv/web/app#!/server/$server/details?key=/library/metadata/".$item['ratingKey'];
+ }else{
+ $address = PLEXURL."/web/index.html#!/server/$server/details?key=/library/metadata/".$item['ratingKey'];
+ }
// If No Overview
if (!isset($itemDetails['Overview'])) { $itemDetails['Overview'] = ''; }
@@ -669,41 +853,15 @@ function resolvePlexItem($server, $token, $item, $nowPlaying = false, $showNames
$image_url = 'ajax.php?a=plex-image&img='.$thumb.'&height='.$height.'&width='.$width.'&key='.$key.'';
}
if(!$thumb){ $image_url = "images/no-np.png"; $key = "no-np"; }
+ $openTab = (PLEXTABNAME) ? "true" : "false";
// Assemble Item And Cache Into Array
if($nowPlaying){
- return '';
+ return '';
}else{
- return ''.$title.' ';
+ return ''.$title.' ';
}
}
-// Create Carousel
-function outputCarousel($header, $size, $type, $items, $script = false) {
- // If None Populate Empty Item
- if (!count($items)) {
- $items = array('Nothing To Show
Get Some Stuff Going! ');
- }
-
- // Set First As Active
- $items[0] = preg_replace('/^/','
', $items[0]);
-
- // Add Buttons
- $buttons = '';
- if (count($items) > 1) {
- $buttons = '
-
Previous
-
Next';
- }
-
- return '
-
-
'.$header.'
-
- '.implode('',$items).'
-
'.$buttons.'
-
'.($script?'':'');
-}
-
//Recent Added
function outputRecentAdded($header, $items, $script = false, $array) {
$hideMenu = '
-
'.$message.'
+ '.$message.'
@@ -2836,5 +3065,431 @@ function buildHomepageNotice($layout, $type, $title, $message){
}
}
+function embyArray($array, $type) {
+ $key = ($type == "video" ? "Height" : "Channels");
+ if (array_key_exists($key, $array)) {
+ switch ($type) {
+ case "video":
+ $codec = $array["Codec"];
+ $height = $array["Height"];
+ $width = $array["Width"];
+ break;
+ default:
+ $codec = $array["Codec"];
+ $channels = $array["Channels"];
+ }
+ return ($type == "video" ? "(".$codec.") (".$width."x".$height.")" : "(".$codec.") (".$channels."ch)");
+ }
+ foreach ($array as $element) {
+ if (is_array($element)) {
+ if (embyArray($element, $type)) {
+ return embyArray($element, $type);
+ }
+ }
+ }
+}
+
+// Get Now Playing Streams From Plex
+function searchPlex($query){
+ $address = qualifyURL(PLEXURL);
+ $openTab = (PLEXTABNAME) ? "true" : "false";
+
+ // Perform API requests
+ $api = @curl_get($address."/search?query=".rawurlencode($query)."&X-Plex-Token=".PLEXTOKEN);
+ $api = simplexml_load_string($api);
+ $getServer = simplexml_load_string(@curl_get($address."/?X-Plex-Token=".PLEXTOKEN));
+ if (!$getServer) { return 'Could not load!'; }
+
+ // Identify the local machine
+ $server = $getServer['machineIdentifier'];
+ $pre = "Cover | Title | Genre | Year | Type | Added | Extra Info |
";
+ $items = "";
+ $albums = $movies = $shows = 0;
+
+ $style = 'style="vertical-align: middle"';
+ foreach($api AS $child) {
+ if($child['type'] != "artist" && $child['type'] != "episode" && isset($child['librarySectionID'])){
+ $time = (string)$child['addedAt'];
+ $time = new DateTime("@$time");
+ $results = array(
+ "title" => (string)$child['title'],
+ "image" => (string)$child['thumb'],
+ "type" => (string)ucwords($child['type']),
+ "year" => (string)$child['year'],
+ "key" => (string)$child['ratingKey']."-search",
+ "ratingkey" => (string)$child['ratingKey'],
+ "genre" => (string)$child->Genre['tag'],
+ "added" => $time->format('Y-m-d'),
+ "extra" => "",
+ );
+ switch ($child['type']){
+ case "album":
+ $push = array(
+ "title" => (string)$child['parentTitle']." - ".(string)$child['title'],
+ );
+ $results = array_replace($results,$push);
+ $albums++;
+ break;
+ case "movie":
+ $push = array(
+ "extra" => "Content Rating: ".(string)$child['contentRating']."
Movie Rating: ".(string)$child['rating'],
+ );
+ $results = array_replace($results,$push);
+ $movies++;
+ break;
+ case "show":
+ $push = array(
+ "extra" => "Seasons: ".(string)$child['childCount']."
Episodes: ".(string)$child['leafCount'],
+ );
+ $results = array_replace($results,$push);
+ $shows++;
+ break;
+ }
+ if (file_exists('images/cache/'.$results['key'].'.jpg')){ $image_url = 'images/cache/'.$results['key'].'.jpg'; }
+ if (file_exists('images/cache/'.$results['key'].'.jpg') && (time() - 604800) > filemtime('images/cache/'.$results['key'].'.jpg') || !file_exists('images/cache/'.$results['key'].'.jpg')) {
+ $image_url = 'ajax.php?a=plex-image&img='.$results['image'].'&height=150&width=100&key='.$results['key'];
+ }
+ if(!$results['image']){ $image_url = "images/no-search.png"; $key = "no-search"; }
+
+ if (substr_count(PLEXURL, ':') == 2) {
+ $link = "https://app.plex.tv/web/app#!/server/$server/details?key=/library/metadata/".$results['ratingkey'];
+ }else{
+ $link = PLEXURL."/web/index.html#!/server/$server/details?key=/library/metadata/".$results['ratingkey'];
+ }
+
+ $items .= '
+ |
+ '.$results['title'].' |
+ '.$results['genre'].' |
+ '.$results['year'].' |
+ '.$results['type'].' |
+ '.$results['added'].' |
+ '.$results['extra'].' |
+
';
+ }
+ }
+ $totals = '
+ '.$movies.'
+ '.$shows.'
+ '.$albums.'
+
';
+ return (!empty($items) ? $totals.$pre.$items."
" : "No Results for $query
" );
+}
+
+function getBannedUsers($string){
+ if (strpos($string, ',') !== false) {
+ $banned = explode(",", $string);
+ }else{
+ $banned = array($string);
+ }
+ return $banned;
+}
+
+function getWhitelist($string){
+ if (strpos($string, ',') !== false) {
+ $whitelist = explode(",", $string);
+ }else{
+ $whitelist = array($string);
+ }
+ foreach($whitelist as &$ip){
+ $ip = is_numeric(substr($ip, 0, 1)) ? $ip : gethostbyname($ip);
+ }
+ return $whitelist;
+}
+
+function get_client_ip() {
+ $ipaddress = '';
+ if (isset($_SERVER['HTTP_CLIENT_IP']))
+ $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
+ else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
+ $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
+ else if(isset($_SERVER['HTTP_X_FORWARDED']))
+ $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
+ else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
+ $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
+ else if(isset($_SERVER['HTTP_FORWARDED']))
+ $ipaddress = $_SERVER['HTTP_FORWARDED'];
+ else if(isset($_SERVER['REMOTE_ADDR']))
+ $ipaddress = $_SERVER['REMOTE_ADDR'];
+ else
+ $ipaddress = 'UNKNOWN';
+ return $ipaddress;
+}
+
+//EMAIL SHIT
+function sendEmail($email, $username = "Organizr User", $subject, $body, $cc = null){
+
+ $mail = new PHPMailer;
+ $mail->isSMTP();
+ $mail->Host = SMTPHOST;
+ $mail->SMTPAuth = SMTPHOSTAUTH;
+ $mail->Username = SMTPHOSTUSERNAME;
+ $mail->Password = SMTPHOSTPASSWORD;
+ $mail->SMTPSecure = SMTPHOSTTYPE;
+ $mail->Port = SMTPHOSTPORT;
+ $mail->setFrom(SMTPHOSTSENDEREMAIL, SMTPHOSTSENDERNAME);
+ $mail->addReplyTo(SMTPHOSTSENDEREMAIL, SMTPHOSTSENDERNAME);
+ $mail->isHTML(true);
+ $mail->addAddress($email, $username);
+ $mail->Subject = $subject;
+ $mail->Body = $body;
+ //$mail->send();
+ if(!$mail->send()) {
+ writeLog("error", "mail failed to send");
+ } else {
+ writeLog("success", "mail has been sent");
+ }
+
+}
+
+function libraryList(){
+ $address = qualifyURL(PLEXURL);
+ $headers = array(
+ "Accept" => "application/json",
+ "X-Plex-Token" => PLEXTOKEN
+ );
+ $getServer = simplexml_load_string(@curl_get($address."/?X-Plex-Token=".PLEXTOKEN));
+ if (!$getServer) { return 'Could not load!'; }else { $gotServer = $getServer['machineIdentifier']; }
+
+ $api = simplexml_load_string(@curl_get("https://plex.tv/api/servers/$gotServer/shared_servers", $headers));
+ $libraryList = array();
+ foreach($api->SharedServer->Section AS $child) {
+ $libraryList['libraries'][(string)$child['title']] = (string)$child['id'];
+ }
+ foreach($api->SharedServer AS $child) {
+ if(!empty($child['username'])){
+ $username = (string)strtolower($child['username']);
+ $libraryList['users'][$username] = (string)$child['id'];
+ }
+ }
+ return (!empty($libraryList) ? array_change_key_case($libraryList,CASE_LOWER) : null );
+}
+
+function plexUserShare($username){
+ $address = qualifyURL(PLEXURL);
+ $headers = array(
+ "Accept" => "application/json",
+ "Content-Type" => "application/json",
+ "X-Plex-Token" => PLEXTOKEN
+ );
+ $getServer = simplexml_load_string(@curl_get($address."/?X-Plex-Token=".PLEXTOKEN));
+ if (!$getServer) { return 'Could not load!'; }else { $gotServer = $getServer['machineIdentifier']; }
+
+ $json = array(
+ "server_id" => $gotServer,
+ "shared_server" => array(
+ //"library_section_ids" => "[26527637]",
+ "invited_email" => $username
+ )
+ );
+
+ $api = curl_post("https://plex.tv/api/servers/$gotServer/shared_servers/", $json, $headers);
+
+ switch ($api['http_code']['http_code']){
+ case 400:
+ writeLog("error", "PLEX INVITE: $username already has access to the shared libraries");
+ $result = "$username already has access to the shared libraries";
+ break;
+ case 401:
+ writeLog("error", "PLEX INVITE: Invalid Plex Token");
+ $result = "Invalid Plex Token";
+ break;
+ case 200:
+ writeLog("success", "PLEX INVITE: $username now has access to your Plex Library");
+ $result = "$username now has access to your Plex Library";
+ break;
+ default:
+ writeLog("error", "PLEX INVITE: unknown error");
+ $result = false;
+ }
+ return (!empty($result) ? $result : null );
+}
+
+function plexUserDelete($username){
+ $address = qualifyURL(PLEXURL);
+ $headers = array(
+ "Accept" => "application/json",
+ "Content-Type" => "application/json",
+ "X-Plex-Token" => PLEXTOKEN
+ );
+ $getServer = simplexml_load_string(@curl_get($address."/?X-Plex-Token=".PLEXTOKEN));
+ if (!$getServer) { return 'Could not load!'; }else { $gotServer = $getServer['machineIdentifier']; }
+ $id = convertPlexName($username, "id");
+
+ $api = curl_delete("https://plex.tv/api/servers/$gotServer/shared_servers/$id", $headers);
+
+ switch ($api['http_code']['http_code']){
+ case 401:
+ writeLog("error", "PLEX INVITE: Invalid Plex Token");
+ $result = "Invalid Plex Token";
+ break;
+ case 200:
+ writeLog("success", "PLEX INVITE: $username doesn't have access to your Plex Library anymore");
+ $result = "$username doesn't have access to your Plex Library anymore";
+ break;
+ default:
+ writeLog("error", "PLEX INVITE: unknown error");
+ $result = false;
+ }
+ return (!empty($result) ? $result : null );
+}
+
+function convertPlexName($user, $type){
+ $array = libraryList();
+ switch ($type){
+ case "username":
+ $plexUser = array_search ($user, $array['users']);
+ break;
+ case "id":
+ if (array_key_exists(strtolower($user), $array['users'])) {
+ $plexUser = $array['users'][strtolower($user)];
+ }
+ break;
+ default:
+ $plexUser = false;
+ }
+ return (!empty($plexUser) ? $plexUser : null );
+}
+
+function randomCode($length = 5, $type = null) {
+ switch ($type){
+ case "alpha":
+ $legend = array_merge(range('A', 'Z'));
+ break;
+ case "numeric":
+ $legend = array_merge(range(0,9));
+ break;
+ default:
+ $legend = array_merge(range(0,9),range('A', 'Z'));
+ }
+ $code = "";
+ for($i=0; $i < $length; $i++) {
+ $code .= $legend[mt_rand(0, count($legend) - 1)];
+ }
+ return $code;
+}
+
+function inviteCodes($action, $code = null, $usedBy = null) {
+ if (!isset($GLOBALS['file_db'])) {
+ $GLOBALS['file_db'] = new PDO('sqlite:'.DATABASE_LOCATION.'users.db');
+ $GLOBALS['file_db']->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ }
+ $now = date("Y-m-d H:i:s");
+
+ switch ($action) {
+ case "get":
+ // Start Array
+ $result = array();
+ // Database Lookup
+ $invites = $GLOBALS['file_db']->query('SELECT * FROM invites WHERE valid = "Yes"');
+ // Get Codes
+ foreach($invites as $row) {
+ array_push($result, $row['code']);
+ }
+ // Return the Results
+ return (!empty($result) ? $result : false );
+ break;
+ case "check":
+ // Start Array
+ $result = array();
+ // Database Lookup
+ $invites = $GLOBALS['file_db']->query('SELECT * FROM invites WHERE valid = "Yes" AND code = "'.$code.'"');
+ // Get Codes
+ foreach($invites as $row) {
+ $result = $row['code'];
+ }
+ // Return the Results
+ return (!empty($result) ? $result : false );
+ break;
+ case "use":
+ $currentIP = get_client_ip();
+ $invites = $GLOBALS['file_db']->query('UPDATE invites SET valid = "No", usedby = "'.$usedBy.'", dateused = "'.$now.'", ip = "'.$currentIP.'" WHERE code = "'.$code.'"');
+ return (!empty($invites) ? true : false );
+ break;
+ }
+
+}
+
+function plexJoin($username, $email, $password){
+ $connectURL = 'https://plex.tv/users.json';
+ $headers = array(
+ 'Accept'=> 'application/json',
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ 'X-Plex-Product' => 'Organizr',
+ 'X-Plex-Version' => '1.0',
+ 'X-Plex-Client-Identifier' => '01010101-10101010',
+ );
+ $body = array(
+ 'user[email]' => $email,
+ 'user[username]' => $username,
+ 'user[password]' => $password,
+ );
+
+ $api = curl_post($connectURL, $body, $headers);
+ $json = json_decode($api['content'], true);
+ $errors = (!empty($json['errors']) ? true : false);
+ $success = (!empty($json['user']) ? true : false);
+ //Use This for later
+ $usernameError = (!empty($json['errors']['username']) ? $json['errors']['username'][0] : false);
+ $emailError = (!empty($json['errors']['email']) ? $json['errors']['email'][0] : false);
+ $passwordError = (!empty($json['errors']['password']) ? $json['errors']['password'][0] : false);
+
+ switch ($api['http_code']['http_code']){
+ case 400:
+ writeLog("error", "PLEX JOIN: $username already has access to the shared libraries");
+ break;
+ case 401:
+ writeLog("error", "PLEX JOIN: invalid Plex Token");
+ break;
+ case 422:
+ writeLog("error", "PLEX JOIN: user info error");
+ break;
+ case 429:
+ writeLog("error", "PLEX JOIN: too many requests to plex.tv please try later");
+ break;
+ case 200:
+ case 201:
+ writeLog("success", "PLEX JOIN: $username now has access to your Plex Library");
+ break;
+ default:
+ writeLog("error", "PLEX JOIN: unknown error, Error: ".$api['http_code']['http_code']);
+ }
+ //prettyPrint($api);
+ //prettyPrint(json_decode($api['content'], true));
+ return (!empty($success) && empty($errors) ? true : false );
+
+}
+
+function getCert(){
+ $url = "http://curl.haxx.se/ca/cacert.pem";
+ $file = getcwd()."/config/cacert.pem";
+ $directory = getcwd()."/config/";
+ @mkdir($directory, 0770, true);
+ if(!file_exists($file)){
+ file_put_contents( $file, fopen($url, 'r'));
+ writeLog("success", "CERT PEM: pem file created");
+ }elseif (file_exists($file) && time() - 2592000 > filemtime($file)) {
+ writeLog("success", "CERT PEM: downloaded new pem file");
+ }
+ return $file;
+}
+
+function customCSS(){
+ if(CUSTOMCSS == "true") {
+ $template_file = "custom.css";
+ $file_handle = fopen($template_file, "rb");
+ echo "\n";
+ echo fread($file_handle, filesize($template_file));
+ fclose($file_handle);
+ echo "\n";
+ }
+}
+
// Always run this
dependCheck();
\ No newline at end of file
diff --git a/homepage.php b/homepage.php
index fa8fd6113..5362dd689 100755
--- a/homepage.php
+++ b/homepage.php
@@ -241,20 +241,13 @@
white-space: normal !important;
width: 0% !important;
font-size: 12px; !important;
- }
+ }
-
@@ -397,6 +390,25 @@ function abortTest() {
+
+
+
+
@@ -474,7 +486,7 @@ function abortTest() {
PLEXRECENTMOVIE, "season" => PLEXRECENTTV, "album" => PLEXRECENTMUSIC);
echo getPlexRecent($plexArray);
}
@@ -483,14 +495,19 @@ function abortTest() {
+
+ role); } ?>
+
+
EMBYRECENTMOVIE, "Episode" => EMBYRECENTTV, "MusicAlbum" => EMBYRECENTMUSIC, "Series" => EMBYRECENTTV);
+ echo getEmbyRecent($embyArray);
+ }
+
?>
+
@@ -525,7 +542,24 @@ function abortTest() {
var closedBox = $(this).closest('div.content-box').remove();
e.preventDefault();
});
-
+
+ $(document).on("click", ".openTab", function(e) {
+ if($(this).attr("openTab") === "true") {
+ var isActive = parent.$("div[data-content-name^='']");
+ var activeFrame = isActive.children('iframe');
+ if(isActive.length === 1){
+ activeFrame.attr("src", $(this).attr("href"));
+ parent.$("li[name='']").trigger("click");
+ }else{
+ parent.$("li[name='']").trigger("click");
+ parent.$("div[data-content-name^='']").children('iframe').attr("src", $(this).attr("href"));
+ }
+ e.preventDefault();
+ }else{
+ console.log("nope");
+ }
+
+ });
function localStorageSupport() {
@@ -533,6 +567,12 @@ function localStorageSupport() {
}
$( document ).ready(function() {
+ $('#plexSearchForm').on('submit', function () {
+ ajax_request('POST', 'search-plex', {
+ searchtitle: $('#plexSearchForm [name=search-title]').val(),
+ }).done(function(data){ $('#resultshere').html(data);});
+
+ });
$('.repeat-btn').click(function(){
var refreshBox = $(this).closest('div.content-box');
$("
").appendTo(refreshBox).fadeIn(300);
@@ -544,26 +584,10 @@ function localStorageSupport() {
},1500);
});
$(document).on('click', '.w-refresh', function(){
- //Your code
var id = $(this).attr("link");
$("div[np^='"+id+"']").toggle();
- console.log(id);
- //console.log(moreInfo);
});
- var windowSize = window.innerWidth;
- var nowPlaying = "";
- if(windowSize >= 1000){
- nowPlaying = 8;
- }else if(windowSize <= 400){
- nowPlaying = 2;
- }else if(windowSize <= 600){
- nowPlaying = 3;
- }else if(windowSize <= 849){
- nowPlaying = 6;
- }else if(windowSize <= 999){
- nowPlaying = 7;
- }
- console.log(windowSize+" - " +nowPlaying);
+
$('.recentItems').slick({
slidesToShow: 13,
@@ -656,7 +680,7 @@ function localStorageSupport() {
$('.js-filter-movie').on('click', function(){
if (movieFiltered === false) {
- $('.recentItems').slick('slickFilter','.item-season, .item-album');
+ $('.recentItems').slick('slickFilter','.item-season, .item-album, .item-Series, .item-Episode, .item-MusicAlbum');
$(this).text('Show Movies');
movieFiltered = true;
} else {
@@ -668,7 +692,7 @@ function localStorageSupport() {
$('.js-filter-season').on('click', function(){
if (seasonFiltered === false) {
- $('.recentItems').slick('slickFilter','.item-movie, .item-album');
+ $('.recentItems').slick('slickFilter','.item-movie, .item-album, .item-Movie, .item-MusicAlbum');
$(this).text('Show TV');
seasonFiltered = true;
} else {
@@ -680,7 +704,7 @@ function localStorageSupport() {
$('.js-filter-album').on('click', function(){
if (albumFiltered === false) {
- $('.recentItems').slick('slickFilter','.item-season, .item-movie');
+ $('.recentItems').slick('slickFilter','.item-season, .item-movie, .item-Series, .item-Episode, .item-Movie');
$(this).text('Show Music');
albumFiltered = true;
} else {
diff --git a/images/css.png b/images/css.png
new file mode 100644
index 000000000..9eb4c0545
Binary files /dev/null and b/images/css.png differ
diff --git a/images/html.png b/images/html.png
new file mode 100644
index 000000000..4b0b1d5a5
Binary files /dev/null and b/images/html.png differ
diff --git a/images/livetv.png b/images/livetv.png
new file mode 100644
index 000000000..8c96275c0
Binary files /dev/null and b/images/livetv.png differ
diff --git a/images/no-list.png b/images/no-list.png
new file mode 100644
index 000000000..5afc8d1f7
Binary files /dev/null and b/images/no-list.png differ
diff --git a/images/no-search.png b/images/no-search.png
new file mode 100644
index 000000000..c95b761f0
Binary files /dev/null and b/images/no-search.png differ
diff --git a/images/platforms/emby.png b/images/platforms/emby.png
new file mode 100644
index 000000000..df2fdd346
Binary files /dev/null and b/images/platforms/emby.png differ
diff --git a/index.php b/index.php
index 8693555c3..1af75efae 100755
--- a/index.php
+++ b/index.php
@@ -40,6 +40,8 @@
$action = $_POST['action'];
unset($_POST['action']);
}
+//Get Invite Code
+$inviteCode = isset($_GET['inviteCode']) ? $_GET['inviteCode'] : null;
// Check for config file
if(!file_exists('config/config.php')) {
@@ -499,13 +501,7 @@
padding: 5px 22px;
}
-
+
@@ -640,7 +636,7 @@
-
+
@@ -652,7 +648,7 @@
-
+
@@ -742,13 +738,13 @@
translate("SPECIFY_LOCATION");?>
-
translate("CURRENT_DIRECTORY");?>:
translate("PARENT_DIRECTORY");?>:
+
translate("CURRENT_DIRECTORY");?>:
translate("PARENT_DIRECTORY");?>:
- authenticated && $configReady == "Yes") : ?>
+ authenticated && $configReady == "Yes") : if(!$inviteCode) : ?>
@@ -915,7 +911,7 @@
error!="") : ?>
Error: error; ?>
-
-
+
authenticated) : ?>
+
+
+
+
+
+
+
+
+
+
+
translate("WELCOME");?>
+
+
+
+
+ error!="") : ?>
+
Error: error; ?>
+
+
+
+
+
translate("HAVE_ACCOUNT");?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1124,10 +1192,10 @@ function notify(notifyString, notifyIcon, notifyType, notifyLength, notifyLayout
}
$('#loginSubmit').click(function() {
- if ($('#login').smkValidate()) {
+ /*if ($('#login').smkValidate()) {
console.log("validated");
}
- console.log("didnt validate");
+ console.log("didnt validate");*/
});
$('#registerSubmit').click(function() {
if ($('#registration').smkValidate()) {
@@ -1153,6 +1221,14 @@ function notify(notifyString, notifyIcon, notifyType, notifyLength, notifyLayout
$("#switchCreateUser").toggle();
$("#welcomeGoBack").toggle();
});
+ $("#plexNoGoBack").click(function(){
+ $("#joinPlexForm").toggle();
+ $("#chooseMethod").toggle();
+ });
+ $("#plexYesGoBack").click(function(){
+ $("#useInviteForm").toggle();
+ $("#chooseMethod").toggle();
+ });
$("#welcomeGoBack2").click(function(){
$( "form[id^='login']" ).toggle();
$("#userPassForm").toggle();
@@ -1187,12 +1263,16 @@ function notify(notifyString, notifyIcon, notifyType, notifyLength, notifyLayout
$(".log-in").click(function(e){
var e1 = document.querySelector(".log-in"),
e2 = document.querySelector(".login-modal");
- cta(e1, e2, {relativeToWindow: true}, function () {
+ cta(e1, e2, {relativeToWindow: true}, function () {
$('.login-modal').modal("show");
});
e.preventDefault();
});
+ //InviteCode
+
+ $('#inviteSet').modal("show");
+
//Logout
$(".logout").click(function(e){
@@ -1222,6 +1302,60 @@ function notify(notifyString, notifyIcon, notifyType, notifyLength, notifyLayout
});
$(document).ready(function(){
+ //PLEX INVITE SHIT
+ $('#checkInviteForm').on('submit', function () {
+ ajax_request('POST', 'validate-invite', {
+ invitecode: $('#checkInviteForm [name=inviteCode]').val(),
+ }).done(function(data){
+ var result = JSON.stringify(data).includes("success");
+ if(result === true){
+ $('#checkInviteForm').hide();
+ $('#chooseMethod').show();
+ console.log(result);
+ }
+ });
+
+ });
+ $('#useInviteForm').on('submit', function () {
+ ajax_request('POST', 'use-invite', {
+ invitecode: $('#useInviteForm [name=inviteCode]').val(),
+ inviteuser: $('#useInviteForm [name=inviteUser]').val(),
+ }).done(function(data){
+ var result = JSON.stringify(data).includes("success");
+ console.log(result);
+ if(result === true){
+ //$('#checkInviteForm').hide();
+ //$('#chooseMethod').show();
+ console.log(result);
+ }
+ });
+
+ });
+ $('#joinPlexForm').on('submit', function () {
+ ajax_request('POST', 'join-plex', {
+ joinuser: $('#joinPlexForm [name=joinUser]').val(),
+ joinemail: $('#joinPlexForm [name=joinEmail]').val(),
+ joinpassword: $('#joinPlexForm [name=joinPassword]').val(),
+ }).done(function(data){
+ var result = JSON.stringify(data).includes("success");
+ if(result === true){
+ $('#joinPlexForm').hide();
+ $('#useInviteForm').show();
+ $('#accountMade').show();
+ $('input[name=inviteUser]').val($('input[name=joinUser]').val());
+ console.log(result);
+ }
+ });
+
+ });
+ $("#yesPlexButton").click(function(){
+ $('#chooseMethod').hide();
+ $('#useInviteForm').show();
+ });
+ $("#noPlexButton").click(function(){
+ $('#chooseMethod').hide();
+ $('#joinPlexForm').show();
+ });
$('#userCreateForm').submit(function(event) {
var formData = {
@@ -1381,13 +1515,21 @@ function notify(notifyString, notifyIcon, notifyType, notifyLength, notifyLayout
return false;
});
- $('#splitView').on('click tap', function(){
-
- $('#splitView').hide();
+ $('#splitView').on('contextmenu', function(e){
+ e.stopPropagation();
+ //$('#splitView').hide();
$("#content").attr("class", "content");
$("li[class^='tab-item rightActive']").attr("class", "tab-item");
$("#contentRight").html('');
-
+ return false;
+ });
+ $('#splitView').on('click tap', function(){
+ var activeFrame = $('#content').find('.active');
+ var getCurrentTab = $("li[class^='tab-item active']");
+ getCurrentTab.removeClass('active');
+ getCurrentTab.find('img').removeClass('TabOpened');
+ $("img[class^='TabOpened']").parents("li").trigger("click");
+ activeFrame.remove();
});
$("li[id^='settings.phpx']").on('click tap', function(){
@@ -1452,7 +1594,7 @@ function notify(notifyString, notifyIcon, notifyType, notifyLength, notifyLayout
$("#content div[class^='iframe active']").attr("class", "iframe hidden");
- $( '
' ).appendTo( "#content" );
+ $( '
' ).appendTo( "#content" );
document.title = thistitle;
// window.location.href = '#' + thisname;
@@ -1507,7 +1649,7 @@ function notify(notifyString, notifyIcon, notifyType, notifyLength, notifyLayout
$("#contentRight div[class^='iframe active']").attr("class", "iframe hidden");
- $( '
' ).appendTo( "#contentRight" );
+ $( '
' ).appendTo( "#contentRight" );
document.title = thistitle;
window.location.href = '#' + thisname;
diff --git a/lang/de.ini b/lang/de.ini
index e66f07278..0f95666b6 100644
--- a/lang/de.ini
+++ b/lang/de.ini
@@ -256,4 +256,30 @@ NOTICE_COLOR = "Notice Color"
NOTICE_TITLE = "Notice Title"
NOTICE_MESSAGE = "Notice Message"
SHOW_NAMES = "Show Names"
-NOTICE_LAYOUT = "Notice Layout"
\ No newline at end of file
+NOTICE_LAYOUT = "Notice Layout"
+RECENT_ITEMS_LIMIT = "Recent Items Limit"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = "Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"
+USERNAME_NAME = "Username or Name"
diff --git a/lang/en.ini b/lang/en.ini
index 1b6470671..cd75b805f 100644
--- a/lang/en.ini
+++ b/lang/en.ini
@@ -256,4 +256,30 @@ NOTICE_COLOR = "Notice Color"
NOTICE_TITLE = "Notice Title"
NOTICE_MESSAGE = "Notice Message"
SHOW_NAMES = "Show Names"
-NOTICE_LAYOUT = "Notice Layout"
\ No newline at end of file
+NOTICE_LAYOUT = "Notice Layout"
+RECENT_ITEMS_LIMIT = "Recent Items Limit"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = "Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"
+USERNAME_NAME = "Username or Name"
diff --git a/lang/es.ini b/lang/es.ini
index 81d53cb3d..9826b093c 100644
--- a/lang/es.ini
+++ b/lang/es.ini
@@ -256,4 +256,30 @@ NOTICE_COLOR = "Notice Color"
NOTICE_TITLE = "Notice Title"
NOTICE_MESSAGE = "Notice Message"
SHOW_NAMES = "Show Names"
-NOTICE_LAYOUT = "Notice Layout"
\ No newline at end of file
+NOTICE_LAYOUT = "Notice Layout"
+RECENT_ITEMS_LIMIT = "Recent Items Limit"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = "Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"
+USERNAME_NAME = "Username or Name"
diff --git a/lang/fr.ini b/lang/fr.ini
index b99076b7a..f92d5bdee 100644
--- a/lang/fr.ini
+++ b/lang/fr.ini
@@ -256,4 +256,30 @@ NOTICE_COLOR = "Notice Color"
NOTICE_TITLE = "Notice Title"
NOTICE_MESSAGE = "Notice Message"
SHOW_NAMES = "Show Names"
-NOTICE_LAYOUT = "Notice Layout"
\ No newline at end of file
+NOTICE_LAYOUT = "Notice Layout"
+RECENT_ITEMS_LIMIT = "Recent Items Limit"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = "Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"
+USERNAME_NAME = "Username or Name"
diff --git a/lang/it.ini b/lang/it.ini
index 4b91af728..75c8e1023 100644
--- a/lang/it.ini
+++ b/lang/it.ini
@@ -256,4 +256,30 @@ NOTICE_COLOR = "Notice Color"
NOTICE_TITLE = "Notice Title"
NOTICE_MESSAGE = "Notice Message"
SHOW_NAMES = "Show Names"
-NOTICE_LAYOUT = "Notice Layout"
\ No newline at end of file
+NOTICE_LAYOUT = "Notice Layout"
+RECENT_ITEMS_LIMIT = "Recent Items Limit"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = "Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"
+USERNAME_NAME = "Username or Name"
diff --git a/lang/nl.ini b/lang/nl.ini
index 7ca96a144..3107d1b59 100644
--- a/lang/nl.ini
+++ b/lang/nl.ini
@@ -256,4 +256,30 @@ NOTICE_COLOR = "Notice Color"
NOTICE_TITLE = "Notice Title"
NOTICE_MESSAGE = "Notice Message"
SHOW_NAMES = "Show Names"
-NOTICE_LAYOUT = "Notice Layout"
\ No newline at end of file
+NOTICE_LAYOUT = "Notice Layout"
+RECENT_ITEMS_LIMIT = "Recent Items Limit"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = "Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"
+USERNAME_NAME = "Username or Name"
diff --git a/lang/pl.ini b/lang/pl.ini
index 009dcbabf..d2d12df50 100644
--- a/lang/pl.ini
+++ b/lang/pl.ini
@@ -256,4 +256,30 @@ NOTICE_COLOR = "Notice Color"
NOTICE_TITLE = "Notice Title"
NOTICE_MESSAGE = "Notice Message"
SHOW_NAMES = "Show Names"
-NOTICE_LAYOUT = "Notice Layout"
\ No newline at end of file
+NOTICE_LAYOUT = "Notice Layout"
+RECENT_ITEMS_LIMIT = "Recent Items Limit"
+ALLOW_SEARCH = "Allow Search"
+CHECK_INVITE = "Enter Invite Code to Procced"
+CODE = "Invite Code"
+INVITE_CODE = "Invite Code"
+DATE_SENT = "Date Sent"
+DATE_USED = "Date Used"
+VALID = "Valid"
+SUBMIT_CODE = "Submit Code"
+IFRAME_CAN_BE_FRAMED = "iFrame Can Be Framed"
+IFRAME_CANNOT_BE_FRAMED = "iFrame Cannot Be Framed"
+CODE_SUCCESS = "Invite Code Has Been Validated"
+CODE_ERROR = "Invite Code is incorrect or not valid"
+HAVE_ACCOUNT = "Do You Have A PLEX Account Already?"
+USERNAME_EMAIL = "Username or E-Mail"
+INVITE_SUCCESS = "You have now been invited, please check your email to accept"
+INVITE_ERROR = "Invite Code not valid, contact admin"
+CREATE_PLEX = "Create PLEX Account"
+JOIN = "Join"
+SIGN_UP = "Sign-up"
+JOIN_SUCCESS = "You have successfully signed up for PLEX, please click join now"
+JOIN_ERROR = "An error occured signing up for PLEX"
+SEND_INVITE = "Create/Mail Invite"
+USED_BY = "Used By"
+ACCOUNT_MADE = "PLEX Account is now created, Click Join now"
+USERNAME_NAME = "Username or Name"
diff --git a/settings.php b/settings.php
index 2c9ad2e75..0e275f07a 100755
--- a/settings.php
+++ b/settings.php
@@ -26,6 +26,9 @@
// Load User List
$gotUsers = $file_db->query('SELECT * FROM users');
+// Load Invite List
+$gotInvites = $file_db->query('SELECT * FROM invites');
+
// Load Colours/Appearance
foreach(loadAppearance() as $key => $value) {
$$key = $value;
@@ -76,8 +79,9 @@
+
-
+
-
+
+
-
-
+
+
+
+
+
-