<commit_before>Ext.define('devilry_subjectadmin.view.managestudents.SingleMetaInfo', {
    extend: 'Ext.Container',
    alias: 'widget.singlegroupmetainfo',
    cls: 'devilry_subjectadmin_singlegroupmetainfo bootstrap',

    requires: [
        'devilry_subjectadmin.utils.UrlLookup'
    ],

    /**
     * @cfg {Ext.data.Model} [groupRecord]
     */

    /**
     * @cfg {String} [assignment_id]
     */

    initComponent: function() {
        Ext.apply(this, {
            layout: 'column',
            items: [{
                xtype: 'box',
                columnWidth: 0.6,
                margin: '0 5 0 0',
                cls: 'gradebox',
                tpl: [
                    '<tpl if="hasFeedback">',
                        '
',
                            '', gettext('Grade') ,': ',

                            '<tpl if="group.feedback.is_passing_grade">',
                                '',
                                    gettext('Passed'),
                                '',
                            '<tpl else>',
                                '',
                                    gettext('Failed'),
                                '',
                            '</tpl>',
                            ' ({group.feedback.grade})',
                            ' (',
                                gettext('Points'), ': {group.feedback.points}',
                            ')',
                            ' - ',
                                gettext('Details'),
                            '',

                            '
',
                                '', gettext('Note'), ': ',
                                gettext('Students can not see their points, only the grade, and if it is failed or passed.'),
                            '',
                        '
',
                    '<tpl else>',
                        '
',
                            gettext('No feedback'),
                        '
',
                    '</tpl>', {
                        getFeedbackCls: function(feedback) {
                            if(feedback.is_passing_grade) {
                                return 'success';
                            } else {
                                return 'warning';
                            }
                        }
                    }
                ],
                data: {
                    group: this.groupRecord.data,
                    hasFeedback: this.groupRecord.get('feedback') !== null,
                    delivery_link_prefix: devilry_subjectadmin.utils.UrlLookup.manageGroupAndShowDeliveryPrefix(
                        this.assignment_id,
                        this.groupRecord.get('id'))
                },
                listeners: {
                    element: 'el',
                    delegate: 'a.active_feedback_link',
                    scope: this,
                    click: function(e) {
                        e.preventDefault();
                        this.fireEvent('active_feedback_link_clicked');
                    }
                }
            }, {
                xtype: 'box',
                cls: 'statusbox',
                columnWidth: 0.4,
                margin: '0 0 0 10',
                tpl: [
                    '
',
                        '<tpl if="group.is_open">',
                            '', gettext('Open'), ': ',
                            '',
                                gettext('The group can add more deliveries.'),
                            '',
                        '<tpl else>',
                            '', gettext('Closed'), ': ',
                            '',
                                gettext('The group can not add more deliveries.'),
                            '',
                        '</tpl>',
                    '
', {
                        getStatusCls: function(is_open) {
                            return is_open? 'success': 'warning';
                        }
                    }
                ],
                data: {
                    group: this.groupRecord.data,
                    examinersNote: gettext('Examiners can open and close a group at any time to allow/prevent deliveries.')
                }
            }]
        });
        this.callParent(arguments);
    }

});
<commit_msg>devilry_subjectadmin...SingleMetaInfo: Minimal change for tests to pass.<commit_after>Ext.define('devilry_subjectadmin.view.managestudents.SingleMetaInfo', {
    extend: 'Ext.Container',
    alias: 'widget.singlegroupmetainfo',
    cls: 'devilry_subjectadmin_singlegroupmetainfo bootstrap',

    requires: [
        'devilry_subjectadmin.utils.UrlLookup'
    ],

    /**
     * @cfg {Ext.data.Model} [groupRecord]
     */

    /**
     * @cfg {String} [assignment_id]
     */

    initComponent: function() {
        Ext.apply(this, {
            layout: 'column',
            items: [{
                xtype: 'box',
                columnWidth: 0.6,
                margin: '0 5 0 0',
                cls: 'gradebox',
                tpl: [
                    '<tpl if="hasFeedback">',
                        '
',
                            '', gettext('Grade') ,': ',

                            '<tpl if="group.feedback.is_passing_grade">',
                                '',
                                    gettext('Passed'),
                                '',
                            '<tpl else>',
                                '',
                                    gettext('Failed'),
                                '',
                            '</tpl>',
                            ' ({group.feedback.grade})',
                            ' (',
                                gettext('Points'), ': {group.feedback.points}',
                            ')',
                            ' - ',
                                gettext('Details'),
                            '',

                            '
',
                                '', gettext('Note'), ': ',
                                gettext('Students can not see their points, only the grade, and if it is failed or passed.'),
                            '',
                        '
',
                    '<tpl else>',
                        '
',
                            gettext('No feedback'),
                        '
',
                    '</tpl>', {
                        getFeedbackCls: function(feedback) {
                            if(feedback.is_passing_grade) {
                                return 'success';
                            } else {
                                return 'warning';
                            }
                        }
                    }
                ],
                data: {
                    group: this.groupRecord.data,
                    hasFeedback: this.groupRecord.get('feedback') !== null,
                    delivery_link_prefix: devilry_subjectadmin.utils.UrlLookup.manageGroupAndShowDeliveryPrefix(
                        this.assignment_id,
                        this.groupRecord.get('id'))
                },
                listeners: {
                    element: 'el',
                    delegate: 'a.active_feedback_link',
                    scope: this,
                    click: function(e) {
                        e.preventDefault();
                        this.fireEvent('active_feedback_link_clicked');
                    }
                }
            }, {
                xtype: 'box',
                cls: 'statusbox',
                columnWidth: 0.4,
                margin: '0 0 0 10',
                tpl: [
                    '
',
                        '<tpl if="group.is_open">',
                            '', gettext('Open'), ': ',
                            '',
                                gettext('The group can add more deliveries.'),
                            '',
                        '<tpl else>',
                            '', gettext('Closed'), ': ',
                            '',
                                gettext('The group can not add more deliveries.'),
                            '',
                        '</tpl>',
                    '
', {
                        getStatusCls: function(is_open) {
                            return is_open? 'success': 'warning';
                        }
                    }
                ],
                data: {
                    group: this.groupRecord.data,
                    examinersNote: gettext('Examiners can open and close a group at any time to allow/prevent deliveries.')
                }
            }]
        });
        this.callParent(arguments);
    }

});
<|endoftext|>


<commit_before>//<%
/**
 * jsUnity Universal JavaScript Testing Framework v0.1
 * http://jsunity.com/
 *
 * Copyright (c) 2009 Ates Goral
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */

/**
 * Assert that the given Boolean expression evaluates to true
 *
 * @param expr The Boolean expression
 */
function assertTrue(expr) {
	if (!expr) {
		throw "Expression does not evaluate to true";
	}
}

/**
 * Assert that the given Boolean expression evaluates to false
 *
 * @param expr The Boolean expression
 */
function assertFalse(expr) {
	if (expr) {
		throw "Condition does not evaluate to false";
	}
}

/**
 * Assert that the given value matches what's expected
 *
 * @param expected The expected value
 * @param actual The actual given value
 */
function assertEquals(expected, actual) {
	if (expected !== actual) {
		throw "Actual value does not match what's expected: [expected] "
			+ expected + ", [actual] " + actual;
	}
}

/**
 * Assert that the given value doesn't match the given unexpected value
 *
 * @param unexpected The unexpected value
 * @param actual The actual given value
 */
function assertNotEquals(unexpected, actual) {
	if (unexpected === actual) {
		throw "Actual value matches the unexpected value: " + actual;
	}
}

/**
 * Assert that the given object is null
 *
 * @param object The given object
 */
function assertNull(object) {
	if (object !== null) {
		throw "Object is not null";
	}
}

/**
 * Assert that the given object is not null
 *
 * @param object The given object
 */
function assertNotNull(object) {
	if (object === null) {
		throw "Object is null";
	}
}

/**
 * Assert that the given object is undefined
 *
 * @param object The given object
 */
function assertUndefined(value) {
	if (value !== undefined) {
		throw "Value is not undefined";
	}
}

/**
 * Assert that the given object is not undefined
 *
 * @param object The given object
 */
function assertNotUndefined(value) {
	if (value === undefined) {
		throw "Value is undefined";
	}
}

/**
 * Assert that the given object is NaN
 *
 * @param object The given object
 */
function assertNaN(value) {
	if (!isNaN(value)) {
		throw "Value is not NaN";
	}
}

/**
 * Assert that the given object is not NaN
 *
 * @param object The given object
 */
function assertNotNaN(value) {
	if (isNaN(value)) {
		throw "Value is NaN";
	}
}

/**
 * Fail the test by throwing an exception
 */
function fail() {
	throw "Test failed";
}

(function () {
	function parseSuiteFunction(suite) {
		var tokens = /^function\s*([^( ]*?)\s*\(.+?\{((?:[^}]*}?)+)}$/.exec(
			suite.toString().split(/[\r\n]/).join(" "));

		if (!tokens) {
			throw "Invalid function.";
		}

		var runnerBody = tokens[2];

		var ret = {
			runner: new Function(runnerBody + "eval(this.fn).call();"),
			//name: tokens[1],
			tests: []
		};

		var fns = runnerBody.match(/function\s+[^(]+/g);

		if (fns) {
			for (var i = 0; i < fns.length; i++) {
				var tokens = /\s(.+)$/.exec(fns[i]);

				if (tokens) {
					var name = tokens[1];

					if (/^test/.test(name)) {
						ret.tests.push(name);
					} else if (/^setUp|tearDown$/.test(name)) {
						ret[name] = true;
					}
				}
			}
		}

		return ret;
	}

	function parseSuite(suite) {
		if (suite instanceof Function) {
			// functions inside function
			return parseSuiteFunction(suite);
		} else if (suite instanceof Array) {
			// array of test function names
			throw "Not implemented";
		} else if (suite instanceof Object) {
			// functions as properties
			throw "Not implemented";
		} else if (typeof suite === "string") {
			// source code of functions
			throw "Not implemented";
		} else {
			throw "Must be a function, array, object or string.";
		}
	}

	jsUnity = {
		log: function () {},

		error: function (s) { this.log("[ERROR] " + s); },

		run: function (s) {
			try {
				var suite = parseSuite(s);
			} catch (e) {
				this.error("Invalid test suite: " + e);
				return false;
			}

			var total = suite.tests.length;
			var passed = 0;

			this.log(total + " tests found");

			for (var i = 0; i < total; i++) {
				var test = suite.tests[i];

				try {
					if (suite.setUp) {
						suite.runner.call({ fn: "setUp" });
					}
					suite.runner.call({ fn: test });
					if (suite.tearDown) {
						suite.runner.call({ fn: "tearDown" });
					}
					passed++;
					this.log("[PASSED] " + test);
				} catch (e) {
					if (suite.tearDown) {
						suite.runner.call({ fn: "tearDown" });
					}
					this.log("[FAILED] " + test + ": " + e);
				}
			}

			var failed = total - passed;

			this.log(passed + " tests passed");
			this.log(failed + " tests failed");

			return {
				total: total,
				passed: passed,
				failed: failed
			}
		}
	};
})();
//%><commit_msg>Moved assertion functions out of global scope. Compiled runner function now uses a with() statement to expose the functions to the tests.<commit_after>//<%
/**
 * jsUnity Universal JavaScript Testing Framework v0.1
 * http://jsunity.com/
 *
 * Copyright (c) 2009 Ates Goral
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */

(function () {
	var defaultAssertions = {
		/**
		 * Assert that the given Boolean expression evaluates to
		 * true
		 *
		 * @param expr The Boolean expression
		 */
		assertTrue: function (expr) {
			if (!expr) {
				throw "Expression does not evaluate to true";
			}
		},

		/**
		 * Assert that the given Boolean expression evaluates to
		 * false
		 *
		 * @param expr The Boolean expression
		 */
		assertFalse: function (expr) {
			if (expr) {
				throw "Condition does not evaluate to false";
			}
		},

		/**
		 * Assert that the given value matches what's expected
		 *
		 * @param expected The expected value
		 * @param actual The actual given value
		 */
		assertEquals: function (expected, actual) {
			if (expected !== actual) {
				throw "Actual value does not match what's expected: [expected] "
					+ expected + ", [actual] " + actual;
			}
		},

		/**
		 * Assert that the given value doesn't match the given unexpected value
		 *
		 * @param unexpected The unexpected value
		 * @param actual The actual given value
		 */
		assertNotEquals: function (unexpected, actual) {
			if (unexpected === actual) {
				throw "Actual value matches the unexpected value: " + actual;
			}
		},

		/**
		 * Assert that the given object is null
		 *
		 * @param object The given object
		 */
		assertNull: function (object) {
			if (object !== null) {
				throw "Object is not null";
			}
		},

		/**
		 * Assert that the given object is not null
		 *
		 * @param object The given object
		 */
		assertNotNull: function (object) {
			if (object === null) {
				throw "Object is null";
			}
		},

		/**
		 * Assert that the given object is undefined
		 *
		 * @param object The given object
		 */
		assertUndefined: function (value) {
			if (value !== undefined) {
				throw "Value is not undefined";
			}
		},

		/**
		 * Assert that the given object is not undefined
		 *
		 * @param object The given object
		 */
		assertNotUndefined: function (value) {
			if (value === undefined) {
				throw "Value is undefined";
			}
		},

		/**
		 * Assert that the given object is NaN
		 *
		 * @param object The given object
		 */
		assertNaN: function (value) {
			if (!isNaN(value)) {
				throw "Value is not NaN";
			}
		},

		/**
		 * Assert that the given object is not NaN
		 *
		 * @param object The given object
		 */
		assertNotNaN: function (value) {
			if (isNaN(value)) {
				throw "Value is NaN";
			}
		},

		/**
		 * Fail the test by throwing an exception
		 */
		fail: function () {
			throw "Test failed";
		}
	};

	function parseSuiteFunction(suite) {
		var tokens = /^function\s*([^( ]*?)\s*\(.+?\{((?:[^}]*}?)+)}$/.exec(
			suite.toString().split(/[\r\n]/).join(" "));

		if (!tokens) {
			throw "Invalid function.";
		}

		var runnerBody = tokens[2];

		var ret = {
			runner: new Function(
				"with (jsUnity.assertions) {"
				+ runnerBody
				+ "} eval(this.fn).call();"),
			//name: tokens[1], // todo: why doesn't this work?
			tests: []
		};

		var fns = runnerBody.match(/function\s+[^(]+/g);

		if (fns) {
			for (var i = 0; i < fns.length; i++) {
				var tokens = /\s(.+)$/.exec(fns[i]);

				if (tokens) {
					var name = tokens[1];

					if (/^test/.test(name)) {
						ret.tests.push(name);
					} else if (/^setUp|tearDown$/.test(name)) {
						ret[name] = true;
					}
				}
			}
		}

		return ret;
	}

	function parseSuite(suite) {
		if (suite instanceof Function) {
			// functions inside function
			return parseSuiteFunction(suite);
		} else if (suite instanceof Array) {
			// array of test function names
			throw "Not implemented";
		} else if (suite instanceof Object) {
			// functions as properties
			throw "Not implemented";
		} else if (typeof suite === "string") {
			// source code of functions
			throw "Not implemented";
		} else {
			throw "Must be a function, array, object or string.";
		}
	}

	jsUnity = {
		assertions: defaultAssertions,

		log: function () {},

		error: function (s) { this.log("[ERROR] " + s); },

		run: function (s) {
			try {
				var suite = parseSuite(s);
			} catch (e) {
				this.error("Invalid test suite: " + e);
				return false;
			}

			var total = suite.tests.length;
			var passed = 0;

			this.log(total + " tests found");

			for (var i = 0; i < total; i++) {
				var test = suite.tests[i];

				try {
					if (suite.setUp) {
						suite.runner.call({ fn: "setUp" });
					}
					suite.runner.call({ fn: test });
					if (suite.tearDown) {
						suite.runner.call({ fn: "tearDown" });
					}
					passed++;
					this.log("[PASSED] " + test);
				} catch (e) {
					if (suite.tearDown) {
						suite.runner.call({ fn: "tearDown" });
					}
					this.log("[FAILED] " + test + ": " + e);
				}
			}

			var failed = total - passed;

			this.log(passed + " tests passed");
			this.log(failed + " tests failed");

			return {
				total: total,
				passed: passed,
				failed: failed
			}
		}
	};
})();
//%><|endoftext|>


<commit_before>var cache={}
  ,swap=function(s,o){return s.replace(/{\w+}/g,function(k){return o[k]||k;});};
var stopAndRender=function(e){
  $.stop(e);
  render($(this).attr('id'));
};

var makeAnchors=function(){
  var $toc=$('.toc');
  var headings="";
  $('#content > h2').each(function(e){
    e.name=e.id;
    e.innerHTML=swap("# ",
      {"{NAME}":e.name
    })+e.innerHTML;
    // link to the anchors in the table of contents
    headings+="
"+e.innerHTML+"
"
  });
  if(headings===""){
    $toc.hide();
  }else{
    $toc.html("
"+headings+"
");
    $toc.show();
    $toc.css("display","block");
  }
};

var render = function(key,back){
  if(!key)return;
  if(key in cache){
    console.log("rendering %s",key);
    $('#main > .header > h1').html("[ "+key+" ]"); // set title of page.
    $('#content').html(cache[key]);
    makeAnchors();
    // make in-page links behave like the nav bar
    $('#content a').each(function(e){
      // determine if it's a local link
      var $e=$(e);
      var link=$e.attr('href')||"!";
      if(link[0]==='/'){ // it's a local link
        $e.on('click',function(e){
          $.stop(e);
          render(link.slice(1));
        });
      }
    });
    if(!back)window.history.pushState("", key, "/"+key);
  }else{
    $.ajax("/"+key+".json",function(k){
      console.log("fetching %s",key);
      cache[key] = marked(JSON.parse(k).txt);
      render(key);
    });
  }
};

$(function(){ // wait until the page has loaded

  (function(){ // UI stuff for responsive menu
    var $layout=$('#layout'),
      $menu=$('#menu'),
      $menuLink=$('#menuLink');
    $menuLink.on('click',function(e){
      $.stop(e);
      $layout.toggleClass('active');
      $menu.toggleClass('active');
      $menuLink.toggleClass('active');
    });
  })();

  // in body links are not currently being treated like sidebar links
  // they trigger a page reload, this should be factored out
  // and applied to all in page links

  $.ajax("/nav.json",function(res){ // get the navigation data
    var nav=JSON.parse(res).nav; // fetch the navigation data
    // On page ready, fill up the sidebar menu..
    $('#nav-list').html(nav.map(function(x){
      return "
"+x+"
";
    }).join(""));
    // if they click a local link, fetch it, cache it, and render it
    $('#nav-list > li > a').on('click',stopAndRender);
  });

// cache the original content, since you won't be fetching it again...
  var base=window.location.pathname.slice(1)||"index";
  cache[base]=$('.content').html();
  render(base);

  window.onpopstate = function(){
    render(window.location.pathname.slice(1)||"index",true);
  };
});
<commit_msg>quick patch to address local link hijacking (clientside)<commit_after>var cache={}
  ,swap=function(s,o){return s.replace(/{\w+}/g,function(k){return o[k]||k;});};
var stopAndRender=function(e){
  $.stop(e);
  render($(this).attr('id'));
};

var makeAnchors=function(){
  var $toc=$('.toc');
  var headings="";
  $('#content > h2').each(function(e){
    e.name=e.id;
    e.innerHTML=swap("# ",
      {"{NAME}":e.name
    })+e.innerHTML;
    // link to the anchors in the table of contents
    headings+="
"+e.innerHTML+"
"
  });
  if(headings===""){
    $toc.hide();
  }else{
    $toc.html("
"+headings+"
");
    $toc.show();
    $toc.css("display","block");
  }
};

var render = function(key,back){
  if(!key)return;
  if(key in cache){
    console.log("rendering %s",key);
    document.title=key;
    $('#main > .header > h1').html("[ /"+key+" ]"); // set title of page.
    $('#content').html(cache[key]);
    makeAnchors();
    // make in-page links behave like the nav bar
    $('#content a').each(function(e){
      // determine if it's a local link
      var $e=$(e);
      var link=$e.attr('href')||"!";
      if(link[0]==='/'&& // it's a local link
        !link.match(/^\/assets\//) // and not an asset
      ){
        $e.on('click',function(e){
          $.stop(e);
          render(link.slice(1));
        });
      }
    });
    if(!back)window.history.pushState("", key, "/"+key);
  }else{
    $.ajax("/"+key+".json",function(k){
      console.log("fetching %s",key);
      cache[key] = marked(JSON.parse(k).txt);
      render(key);
    });
  }
};

$(function(){ // wait until the page has loaded

  (function(){ // UI stuff for responsive menu
    var $layout=$('#layout'),
      $menu=$('#menu'),
      $menuLink=$('#menuLink');
    $menuLink.on('click',function(e){
      $.stop(e);
      $layout.toggleClass('active');
      $menu.toggleClass('active');
      $menuLink.toggleClass('active');
    });
  })();

  // in body links are not currently being treated like sidebar links
  // they trigger a page reload, this should be factored out
  // and applied to all in page links

  $.ajax("/nav.json",function(res){ // get the navigation data
    var nav=JSON.parse(res).nav; // fetch the navigation data
    // On page ready, fill up the sidebar menu..
    $('#nav-list').html(nav.map(function(x){
      return "
"+x+"
";
    }).join(""));
    // if they click a local link, fetch it, cache it, and render it
    $('#nav-list > li > a').on('click',stopAndRender);
  });

// cache the original content, since you won't be fetching it again...
  var base=window.location.pathname.slice(1)||"index";
  cache[base]=$('.content').html();
  render(base);

  window.onpopstate = function(){
    render(window.location.pathname.slice(1)||"index",true);
  };
});
<|endoftext|>


<commit_before>/**
 * A UI component for searching OSF projects and components with typeahead.
 * Depends on typeahead.js.
 */
;(function (global, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof $script === 'function') {
        $script.ready(['typeahead'], function() {
            global.TypeaheadSearch = factory(jQuery);
            $script.done('typeaheadSearch');
        });
    } else {
        global.TypeaheadSearch = factory(jQuery);
    }
}(this, function ($) {
    'use strict';

    var substringMatcher = function(strs) {
        return function findMatches(q, cb) {

            // an array that will be populated with substring matches
            var matches = [];

            // regex used to determine if a string contains the substring `q`

            var substrRegex = new RegExp(q, 'i');
            var count = 0;
            // iterate through the pool of strings and for any string that
            // contains the substring `q`, add it to the `matches` array
            $.each(strs, function(i, str) {
            if (substrRegex.test(str.name)) {
                count += 1;
                // the typeahead jQuery plugin expects suggestions to a
                // JavaScript object, refer to typeahead docs for more info
                matches.push({ value: str });

                //alex's hack to limit number of results
                if(count > 14){
                    return false;
                }
                // above you can return name or a dict of name/node id,
            }
            // add an event to the input box -- listens for keystrokes and if there is a keystroke then it should clearrr
            //
            });

            cb(matches);
        };
    };

    function initSelectedOption(inputProject, clearInputProject,
                                     addLink, namespace, nodeType, componentBool){
        //  once a typeahead option is selected, enable the button and assign the add_link variable for use later
        inputProject.bind('typeahead:selected', function(obj, datum) {
            var linkID = datum.value.node_id;
            var routeID = datum.value.route;
            clearInputProject.show();

            inputProject.css('background-color', '#f5f5f5')
                .attr('disabled', true)
                .css('border', '2px solid LightGreen');

            addLink.prop('linkID' + nodeType, linkID)
                .removeAttr('disabled')
                .prop('routeID'+ nodeType, routeID);
            if(componentBool){

                var parentNode = $('#addLink' + namespace).prop('linkID' + nodeType);
                $.getJSON('/api/v1/project/'+ parentNode +'/get_children/', function (projects) {
                    var myProjects = projects.nodes.map(
                        function(item){return {
                            'name': item.title,
                            'node_id': item.id,
                            'route': item.api_url,
                        };
                    });

                    if(myProjects.length > 0){
                        $('#inputComponent' + namespace).data('ttTypeahead').dropdown.datasets[0].source = substringMatcher(myProjects);
                        $('#inputComponent' + namespace).attr('disabled', false);
                        $('#inputComponent' + namespace).focus();
                        $('#inputComponent' + namespace).attr('placeholder', 'Type to search');
                    } else{
                        $('#inputComponent' + namespace).attr('disabled', true);
                        $('#inputComponent' + namespace).attr('placeholder', 'Selected project has no components');
                    }
                });
            }
        });
    }

    // add listeners to clear inputs
    function typeaheadAddListener(clearInputProject, inputProject,
                                   addLink, namespace, nodeType, componentBool){
        clearInputProject[0].addEventListener('click', function() {
            clearInputProject.hide();

            inputProject.attr('disabled', false)
                .css('background-color', '')
                .css('border-color','#ccc')
                .val('');

            addLink.removeProp('linkID' + nodeType)
                .removeProp('routeID' + nodeType);

            if(componentBool){
                $('#clearInputComponent' + namespace).click();
                $('#inputComponent' + namespace).attr('disabled', true);
                $('#inputComponent' + namespace).attr('placeholder', 'First select a project');
            }

            if(nodeType === 'Project'){
                addLink.attr('disabled', true);
            }
        });
    }

    function initTypeahead(nodeType, namespace, myProjects){
        $('#input' + nodeType + namespace).typeahead({
            hint: false,
            highlight: true,
            minLength: 0
        },
        {
            name: 'projectSearch' + nodeType + namespace,
            displayKey: function(data){
                return data.value.name;
        },
            source: substringMatcher(myProjects)
        });
    }

    // logic for typeahead searching user's projects
    function initComponentTypeahead(namespace, nodeType, componentBool){
        var myProjects = [];
        var $addLink = $('#addLink' + namespace);
        var $clearInputProject = $('#clearInput' + nodeType + namespace);
        var $inputProject = $('#input'+ nodeType + namespace);

        initSelectedOption($inputProject, $clearInputProject,
                                $addLink, namespace, nodeType, componentBool);
        typeaheadAddListener($clearInputProject, $inputProject,
                              $addLink, namespace, nodeType, componentBool);
        initTypeahead(nodeType, namespace, myProjects);
    }

    // logic for typeahead searching a project's componenets
    function initProjectTypeahead(namespace, nodeType, componentBool){
        $.getJSON('/api/v1/dashboard/get_nodes/', function (projects) {

            var myProjects = projects.nodes.map(
                function(item){return {
                    'name': item.title,
                    'node_id': item.id,
                    'route': item.api_url,
                };
            });

            var $addLink = $('#addLink' + namespace);
            var $clearInputProject = $('#clearInput' + nodeType + namespace);
            var $inputProject = $('#input'+ nodeType + namespace);

            initSelectedOption($inputProject, $clearInputProject,
                                    $addLink, namespace, nodeType, componentBool);
            typeaheadAddListener($clearInputProject, $inputProject,
                                  $addLink, namespace, nodeType, componentBool);
            initTypeahead(nodeType, namespace, myProjects);
        });
    }

    function TypeaheadSearch(namespace, nodeType, componentBool) {
        if(nodeType === 'Project'){
            initProjectTypeahead(namespace, nodeType, componentBool);
        }else{
            initComponentTypeahead(namespace, nodeType, componentBool);
        }
    }

    return TypeaheadSearch;
}));
<commit_msg>Add missing error JS error handler<commit_after>/**
 * A UI component for searching OSF projects and components with typeahead.
 * Depends on typeahead.js.
 */
;(function (global, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof $script === 'function') {
        $script.ready(['typeahead'], function() {
            global.TypeaheadSearch = factory(jQuery);
            $script.done('typeaheadSearch');
        });
    } else {
        global.TypeaheadSearch = factory(jQuery);
    }
}(this, function ($) {
    'use strict';

    var substringMatcher = function(strs) {
        return function findMatches(q, cb) {

            // an array that will be populated with substring matches
            var matches = [];

            // regex used to determine if a string contains the substring `q`

            var substrRegex = new RegExp(q, 'i');
            var count = 0;
            // iterate through the pool of strings and for any string that
            // contains the substring `q`, add it to the `matches` array
            $.each(strs, function(i, str) {
            if (substrRegex.test(str.name)) {
                count += 1;
                // the typeahead jQuery plugin expects suggestions to a
                // JavaScript object, refer to typeahead docs for more info
                matches.push({ value: str });

                //alex's hack to limit number of results
                if(count > 14){
                    return false;
                }
                // above you can return name or a dict of name/node id,
            }
            // add an event to the input box -- listens for keystrokes and if there is a keystroke then it should clearrr
            //
            });

            cb(matches);
        };
    };

    function initSelectedOption(inputProject, clearInputProject,
                                     addLink, namespace, nodeType, componentBool){
        //  once a typeahead option is selected, enable the button and assign the add_link variable for use later
        inputProject.bind('typeahead:selected', function(obj, datum) {
            var linkID = datum.value.node_id;
            var routeID = datum.value.route;
            clearInputProject.show();

            inputProject.css('background-color', '#f5f5f5')
                .attr('disabled', true)
                .css('border', '2px solid LightGreen');

            addLink.prop('linkID' + nodeType, linkID)
                .removeAttr('disabled')
                .prop('routeID'+ nodeType, routeID);
            if(componentBool){

                var parentNode = $('#addLink' + namespace).prop('linkID' + nodeType);
                $.getJSON('/api/v1/project/'+ parentNode +'/get_children/', function (projects) {
                    var myProjects = projects.nodes.map(
                        function(item){return {
                            'name': item.title,
                            'node_id': item.id,
                            'route': item.api_url,
                        };
                    });

                    if(myProjects.length > 0){
                        $('#inputComponent' + namespace).data('ttTypeahead').dropdown.datasets[0].source = substringMatcher(myProjects);
                        $('#inputComponent' + namespace).attr('disabled', false);
                        $('#inputComponent' + namespace).focus();
                        $('#inputComponent' + namespace).attr('placeholder', 'Type to search');
                    } else{
                        $('#inputComponent' + namespace).attr('disabled', true);
                        $('#inputComponent' + namespace).attr('placeholder', 'Selected project has no components');
                    }
                });
            }
        });
    }

    // add listeners to clear inputs
    function typeaheadAddListener(clearInputProject, inputProject,
                                   addLink, namespace, nodeType, componentBool){
        clearInputProject[0].addEventListener('click', function() {
            clearInputProject.hide();

            inputProject.attr('disabled', false)
                .css('background-color', '')
                .css('border-color','#ccc')
                .val('');

            addLink.removeProp('linkID' + nodeType)
                .removeProp('routeID' + nodeType);

            if(componentBool){
                $('#clearInputComponent' + namespace).click();
                $('#inputComponent' + namespace).attr('disabled', true);
                $('#inputComponent' + namespace).attr('placeholder', 'First select a project');
            }

            if(nodeType === 'Project'){
                addLink.attr('disabled', true);
            }
        });
    }

    function initTypeahead(nodeType, namespace, myProjects){
        $('#input' + nodeType + namespace).typeahead({
            hint: false,
            highlight: true,
            minLength: 0
        },
        {
            name: 'projectSearch' + nodeType + namespace,
            displayKey: function(data){
                return data.value.name;
        },
            source: substringMatcher(myProjects)
        });
    }

    // logic for typeahead searching user's projects
    function initComponentTypeahead(namespace, nodeType, componentBool){
        var myProjects = [];
        var $addLink = $('#addLink' + namespace);
        var $clearInputProject = $('#clearInput' + nodeType + namespace);
        var $inputProject = $('#input'+ nodeType + namespace);

        initSelectedOption($inputProject, $clearInputProject,
                                $addLink, namespace, nodeType, componentBool);
        typeaheadAddListener($clearInputProject, $inputProject,
                              $addLink, namespace, nodeType, componentBool);
        initTypeahead(nodeType, namespace, myProjects);
    }

    // logic for typeahead searching a project's componenets
    function initProjectTypeahead(namespace, nodeType, componentBool){
        var url = '/api/v1/dashboard/get_nodes/';
        var request = $.getJSON(url, function (projects) {

            var myProjects = projects.nodes.map(
                function(item){return {
                    'name': item.title,
                    'node_id': item.id,
                    'route': item.api_url,
                };
            });

            var $addLink = $('#addLink' + namespace);
            var $clearInputProject = $('#clearInput' + nodeType + namespace);
            var $inputProject = $('#input'+ nodeType + namespace);

            initSelectedOption($inputProject, $clearInputProject,
                                    $addLink, namespace, nodeType, componentBool);
            typeaheadAddListener($clearInputProject, $inputProject,
                                  $addLink, namespace, nodeType, componentBool);
            initTypeahead(nodeType, namespace, myProjects);
        });
        request.fail(function(xhr, textStatus, error) {
            Raven.captureMessage('Could not fetch dashboard nodes.', {
                url: url, textStatus: textStatus, error: error
            });
        });
    }

    function TypeaheadSearch(namespace, nodeType, componentBool) {
        if(nodeType === 'Project'){
            initProjectTypeahead(namespace, nodeType, componentBool);
        }else{
            initComponentTypeahead(namespace, nodeType, componentBool);
        }
    }

    return TypeaheadSearch;
}));
<|endoftext|>


<commit_before>import React from 'react';
import Analyzer from 'Parser/Core/Analyzer';

import SPELLS from 'common/SPELLS';
import TraitStatisticBox, { STATISTIC_ORDER } from 'Interface/Others/TraitStatisticBox';
import { calculateAzeriteEffects } from 'common/stats';
import { formatNumber, formatThousands } from 'common/format';

// Example Log: https://www.warcraftlogs.com/reports/7rLHkgCBhJZ3t1KX#fight=6&type=healing
class SacredFlame extends Analyzer {
  holyFireCasts = 0;
  holyFireTicks = 0;
  holyFireDamage = 0;
  damageBonus = 0;
  manaBonus = 0;
  manaSpentOnHolyFire = 0;

  constructor(...args) {
    super(...args);
    this.active = this.selectedCombatant.hasTrait(SPELLS.SACRED_FLAME.id);
    this.ranks = this.selectedCombatant.traitRanks(SPELLS.SACRED_FLAME.id) || [];

    this.damageBonus = this.ranks.map((rank) => calculateAzeriteEffects(SPELLS.SACRED_FLAME.id, rank)[0]).reduce((total, bonus) => total + bonus, 0);
    this.manaBonus = this.ranks.map((rank) => calculateAzeriteEffects(SPELLS.SACRED_FLAME.id, rank)[1]).reduce((total, bonus) => total + bonus, 0);
  }

  get addedDamage() {
    return this.holyFireCasts * this.damageBonus;
  }

  get extraManaRegen() {
    return (this.holyFireTicks * this.manaBonus) - this.manaSpentOnHolyFire;
  }

  on_byPlayer_cast(event) {
    const spellId = event.ability.guid;

    if (spellId === SPELLS.HOLY_FIRE.id) {
      if (event.classResources) {
        this.manaSpentOnHolyFire += event.classResources[0].cost;
      }
      this.holyFireCasts++;
    }
  }

  on_byPlayer_damage(event) {
    const spellId = event.ability.guid;
    if (spellId === SPELLS.HOLY_FIRE.id) {
      this.holyFireDamage += event.amount;
      this.holyFireTicks++;
    }
  }

  statistic() {
    return (
      <TraitStatisticBox
        position={STATISTIC_ORDER.OPTIONAL()}
        trait={SPELLS.SACRED_FLAME.id}
        value={(
          <React.Fragment>
            {formatThousands(this.extraManaRegen)} Mana gained

            {formatThousands(this.addedDamage)} Additional Damage
          </React.Fragment>
        )}
        tooltip={`
          ${formatNumber(this.holyFireCasts)} total holy fire cast(s).
        `}
      />
    );
  }
}

export default SacredFlame;
<commit_msg>fixing sacred flame scaling<commit_after>import React from 'react';
import Analyzer from 'Parser/Core/Analyzer';

import SPELLS from 'common/SPELLS';
import TraitStatisticBox, { STATISTIC_ORDER } from 'Interface/Others/TraitStatisticBox';
import { calculateAzeriteEffects } from 'common/stats';
import { formatNumber, formatThousands } from 'common/format';

// Example Log: https://www.warcraftlogs.com/reports/7rLHkgCBhJZ3t1KX#fight=6&type=healing
class SacredFlame extends Analyzer {
  holyFireCasts = 0;
  holyFireTicks = 0;
  holyFireDamage = 0;
  damageBonus = 0;
  manaBonus = 0;
  manaSpentOnHolyFire = 0;

  constructor(...args) {
    super(...args);
    this.active = this.selectedCombatant.hasTrait(SPELLS.SACRED_FLAME.id);
    this.ranks = this.selectedCombatant.traitRanks(SPELLS.SACRED_FLAME.id) || [];

    this.damageBonus = this.ranks.map((rank) => calculateAzeriteEffects(SPELLS.SACRED_FLAME.id, rank)[0]).reduce((total, bonus) => total + bonus, 0);
    this.manaBonus = this.ranks.map((rank) => calculateAzeriteEffects(SPELLS.SACRED_FLAME.id, rank, -7)[1]).reduce((total, bonus) => total + bonus, 0);
  }

  get addedDamage() {
    return this.holyFireCasts * this.damageBonus;
  }

  get extraManaRegen() {
    return (this.holyFireTicks * this.manaBonus) - this.manaSpentOnHolyFire;
  }

  on_byPlayer_cast(event) {
    const spellId = event.ability.guid;

    if (spellId === SPELLS.HOLY_FIRE.id) {
      if (event.classResources) {
        this.manaSpentOnHolyFire += event.classResources[0].cost;
      }
      this.holyFireCasts++;
    }
  }

  on_byPlayer_damage(event) {
    const spellId = event.ability.guid;
    if (spellId === SPELLS.HOLY_FIRE.id) {
      this.holyFireDamage += event.amount;
      this.holyFireTicks++;
    }
  }

  statistic() {
    return (
      <TraitStatisticBox
        position={STATISTIC_ORDER.OPTIONAL()}
        trait={SPELLS.SACRED_FLAME.id}
        value={(
          <React.Fragment>
            {formatThousands(this.extraManaRegen)} Mana gained

            {formatThousands(this.addedDamage)} Additional Damage
          </React.Fragment>
        )}
        tooltip={`
          ${formatNumber(this.holyFireCasts)} total holy fire cast(s).
        `}
      />
    );
  }
}

export default SacredFlame;
<|endoftext|>


<commit_before><commit_msg>Add ideas.js to filter ideas<commit_after><|endoftext|>


<commit_before>/**
 * 页面ready方法
 */
$(document).ready(function() {

    categoryDisplay();
    generateContent();
    backToTop();
});

/**
 * load方法，页面的加载完成后触发
 * {fixFooterInit();} 固定Footer栏
 */
/*$(window).load(function() {
    fixFooterInit();
});*/

/**
 * 固定底栏的初始化方法
 * 在一开始载入页面时，使用fixFooter()方法固定底栏。
 * 在浏览器窗口改变大小是，依然固定底栏
 * @return {[type]} [description]
 */
function fixFooterInit() {
    var footerHeight = $('footer').outerHeight();
    var footerMarginTop = getFooterMarginTop() - 0; //类型转换
    // var footerMarginTop = 80;

    fixFooter(footerHeight, footerMarginTop); //fix footer at the beginning

    $(window).resize(function() { //when resize window, footer can auto get the postion
        fixFooter(footerHeight, footerMarginTop);
    });

    /*    $('body').click(function() {
        fixFooter(footerHeight, footerMarginTop);
    });*/

}

/**
 * 固定底栏
 * @param  {number} footerHeight    底栏高度
 * @param  {number} footerMarginTop 底栏MarginTop
 * @return {[type]}                 [description]
 */
function fixFooter(footerHeight, footerMarginTop) {
    var windowHeight = $(window).height();
    var contentHeight = $('body>.container').outerHeight() + $('body>.container').offset().top + footerHeight + footerMarginTop;
    // console.log("window---"+windowHeight);
    // console.log("$('body>.container').outerHeight()---"+$('body>.container').outerHeight() );
    // console.log("$('body>.container').height()---"+$('body>.container').height() );
    // console.log("$('#main').height()--------"+$('#main').height());
    // console.log("$('body').height()--------"+$('body').height());
    //console.log("$('#main').html()--------"+$('#main').html());
    // console.log("$('body>.container').offset().top----"+$('body>.container').offset().top);
    // console.log("footerHeight---"+footerHeight);
    // console.log("footerMarginTop---"+footerMarginTop);
    if (contentHeight < windowHeight) {
        $('footer').addClass('navbar-fixed-bottom');
    } else {
        $('footer').removeClass('navbar-fixed-bottom');
    }

    $('footer').show(400);
}

/**
 * 使用正则表达式得到底栏的MarginTop
 * @return {string} 底栏的MarginTop
 */
function getFooterMarginTop() {
    var margintop = $('footer').css('marginTop');
    var patt = new RegExp("[0-9]*");
    var re = patt.exec(margintop);
    // console.log(re[0]);
    return re[0];
}

/**
 * 分类展示
 * 点击右侧的分类展示时
 * 左侧的相关裂变展开或者收起
 * @return {[type]} [description]
 */
function categoryDisplay() {
    /*show category when click categories list*/
    $('.categories-list-item').click(function() {
        var cate = $(this).attr('cate'); //get category's name

        if(cate === 'All'){
            $('.post-list-body article').show();
        }else{
            $('.post-list-body>div[data-category!=' + cate + ']').hide();
            $('.post-list-body>div[data-category=' + cate + ']').show();
        }
    });
}

/**
 * 回到顶部
 */
function backToTop() {
    //滚页面才显示返回顶部
    $(window).scroll(function() {
        if ($(window).scrollTop() > 100) {
            $("#top").fadeIn(500);
        } else {
            $("#top").fadeOut(500);
        }
    });
    //点击回到顶部
    $("#top").click(function() {
        $("body").animate({
            scrollTop: "0"
        }, 500);
    });

    //初始化tip
    $(function() {
        $('[data-toggle="tooltip"]').tooltip();
    });
}

/**
 * 侧边目录
 */
function generateContent() {

    // console.log($('#markdown-toc').html());
    if (typeof $('#markdown-toc').html() === 'undefined') {
        // $('#content .content-text').html('

文本较短，暂无目录

');
        $('#content').hide();
        $('#myArticle').removeClass('col-sm-9').addClass('col-sm-12');
    } else {
        $('#content .content-text').html('
' + $('#markdown-toc').html() + '
');
        /*   //数据加载完成后，加固定边栏
        $('#myAffix').attr({
            'data-spy': 'affix',
            'data-offset': '50'
        });*/
    }
}<commit_msg>change style<commit_after>/**
 * 页面ready方法
 */
$(document).ready(function() {

    categoryDisplay();
    generateContent();
    backToTop();
});

/**
 * load方法，页面的加载完成后触发
 * {fixFooterInit();} 固定Footer栏
 */
/*$(window).load(function() {
    fixFooterInit();
});*/

/**
 * 固定底栏的初始化方法
 * 在一开始载入页面时，使用fixFooter()方法固定底栏。
 * 在浏览器窗口改变大小是，依然固定底栏
 * @return {[type]} [description]
 */
function fixFooterInit() {
    var footerHeight = $('footer').outerHeight();
    var footerMarginTop = getFooterMarginTop() - 0; //类型转换
    // var footerMarginTop = 80;

    fixFooter(footerHeight, footerMarginTop); //fix footer at the beginning

    $(window).resize(function() { //when resize window, footer can auto get the postion
        fixFooter(footerHeight, footerMarginTop);
    });

    /*    $('body').click(function() {
        fixFooter(footerHeight, footerMarginTop);
    });*/

}

/**
 * 固定底栏
 * @param  {number} footerHeight    底栏高度
 * @param  {number} footerMarginTop 底栏MarginTop
 * @return {[type]}                 [description]
 */
function fixFooter(footerHeight, footerMarginTop) {
    var windowHeight = $(window).height();
    var contentHeight = $('body>.container').outerHeight() + $('body>.container').offset().top + footerHeight + footerMarginTop;
    // console.log("window---"+windowHeight);
    // console.log("$('body>.container').outerHeight()---"+$('body>.container').outerHeight() );
    // console.log("$('body>.container').height()---"+$('body>.container').height() );
    // console.log("$('#main').height()--------"+$('#main').height());
    // console.log("$('body').height()--------"+$('body').height());
    //console.log("$('#main').html()--------"+$('#main').html());
    // console.log("$('body>.container').offset().top----"+$('body>.container').offset().top);
    // console.log("footerHeight---"+footerHeight);
    // console.log("footerMarginTop---"+footerMarginTop);
    if (contentHeight < windowHeight) {
        $('footer').addClass('navbar-fixed-bottom');
    } else {
        $('footer').removeClass('navbar-fixed-bottom');
    }

    $('footer').show(400);
}

/**
 * 使用正则表达式得到底栏的MarginTop
 * @return {string} 底栏的MarginTop
 */
function getFooterMarginTop() {
    var margintop = $('footer').css('marginTop');
    var patt = new RegExp("[0-9]*");
    var re = patt.exec(margintop);
    // console.log(re[0]);
    return re[0];
}

/**
 * 分类展示
 * 点击右侧的分类展示时
 * 左侧的相关裂变展开或者收起
 * @return {[type]} [description]
 */
function categoryDisplay() {
    /*show category when click categories list*/
    $('.categories-list-item').click(function() {
        var cate = $(this).attr('cate'); //get category's name

        if(cate === 'All'){
            $('.post-list-body article').show();
        }else{
            $('.post-list-body>article[data-category!=' + cate + ']').hide();
            $('.post-list-body>article[data-category=' + cate + ']').show();
        }
    });
}

/**
 * 回到顶部
 */
function backToTop() {
    //滚页面才显示返回顶部
    $(window).scroll(function() {
        if ($(window).scrollTop() > 100) {
            $("#top").fadeIn(500);
        } else {
            $("#top").fadeOut(500);
        }
    });
    //点击回到顶部
    $("#top").click(function() {
        $("body").animate({
            scrollTop: "0"
        }, 500);
    });

    //初始化tip
    $(function() {
        $('[data-toggle="tooltip"]').tooltip();
    });
}

/**
 * 侧边目录
 */
function generateContent() {

    // console.log($('#markdown-toc').html());
    if (typeof $('#markdown-toc').html() === 'undefined') {
        // $('#content .content-text').html('

文本较短，暂无目录

');
        $('#content').hide();
        $('#myArticle').removeClass('col-sm-9').addClass('col-sm-12');
    } else {
        $('#content .content-text').html('
' + $('#markdown-toc').html() + '
');
        /*   //数据加载完成后，加固定边栏
        $('#myAffix').attr({
            'data-spy': 'affix',
            'data-offset': '50'
        });*/
    }
}<|endoftext|>


<commit_before>$(document).ready(function() {

  // helper functions

  var settings_buttons = '
Settings

Remove
';

  function construct_inactive_module(name, title) {
    return '
' + settings_buttons + '
' + title + '

';
  }

  function confirmation_dialog(customsettings) {
    var settings = {
      question: 'Are you sure?',
      confirm: function() {},
      cancel: function() {}
    };

    if (customsettings !== undefined) {
      $.extend(settings, customsettings);
    }

    var dialog = '

' + settings.question + '

Yes

No

';

    $('body').append(dialog);

    $('#confirmation_dialog').showPopup({
      dispose: true,
      on_confirm: settings.confirm,
      on_close: settings.cancel
    });
  }

  // get/poll module

  function get_module(module, customsettings) {
    var settings = {
      poll: 0,
      placeholder: $('.placeholder[data-module=' + module + ']'),
      params: []
    }

    if (customsettings !== undefined) {
      $.extend(settings, customsettings);
    }

    var url = '/xhr/' + module;

    for (var i=0; i < settings.params.length; i++) {
      url += '/' + settings.params[i];
    }

    $.get(url, function(data) {
      var module_ele = $('#' + module);

      // if module is already on page
      if (module_ele.length > 0) {

        // if module has been returned by the XHR view
        if ($(data).attr('id') === module) {
          module_ele.replaceWith(data);

        // else placeholder has been returned by the XHR view
        } else {
          module_ele.fadeOut(200, function() {
            $(this).replaceWith(data);
          });
        }

      // placeholder is on page
      } else {
        var new_module = $(data).hide();
        settings.placeholder.replaceWith(new_module);
        $('.module[data-module=' + module + ']').fadeIn(200);
      }
    });

    // poll
    if (settings.poll !== 0) {
      setTimeout(function() {
        get_module(module, {
          poll: settings.poll
        })
      }, settings.poll * 1000);
    }
  }

  // initialise modules on page load

  function init_modules() {
    $('.placeholder:not(.initialised)').each(function() {
      $(this).addClass('initialised');
      var delay = $(this).data('delay');
      if (delay === undefined) {
        get_module($(this).data('module'), {
          poll: $(this).data('poll')
        });
      } else {
        var module = $(this).data('module');
        var poll = $(this).data('poll');
        setTimeout(function() {
          get_module(module, {
            poll: poll
          });
        }, delay * 1000);
      }
    });
  }

  init_modules();

  // currently playing

  var currently_playing_id = null;

  function get_currently_playing() {
    $.get('/xhr/currently_playing', function(data) {

      if (data.playing === false) {

        // hide currently playing
        $('#currently_playing').slideUp(200, function() {
          $(this).remove();
        });

        // hide synopsis module if visible
        $('#synopsis').fadeOut(200, function() {
          $(this).replaceWith(construct_inactive_module('synopsis', 'Synopsis'));
        });

        // hide trakt module if visible
        $('#trakt').fadeOut(200, function() {
          $(this).replaceWith(construct_inactive_module('trakt', 'trakt.tv'));
        });

        currently_playing_id = null;

      } else {
        var currently_playing_module = $('#currently_playing');

        if (currently_playing_module.length > 0) {
          currently_playing_module.replaceWith(data);

        } else {
          var module = $(data).hide();
          $('body').append(module);
          $('#currently_playing').slideDown(200);
        }

        // use fanart of currently playing item as background if enabled in settings

        if ($('body').data('fanart_backgrounds') === 'True') {
          var fanart_url = $('#currently_playing').data('fanart');
          if (fanart_url !== undefined) {
            var img = new Image();
            img.onload = function() {
              var fanart = $('#fanart');
              fanart.css('background-image', 'url(' + fanart_url + ')');
              if (!fanart.is(':visible')) {
                fanart.fadeIn(500);
              }
            };
            img.src = fanart_url;
          }
        }

        // synopsis

        // if synopsis module is enabled
        var synopsis_module = $('#synopsis, #synopsis_inactive');
        if (synopsis_module.length > 0) {

          // if currently playing item has a synopsis
          var synopsis = $('#currently_playing .synopsis');
          if (synopsis.length > 0) {
            var module = $('
' + settings_buttons + '

');
            module.find('h2').replaceWith(synopsis.find('h2'));
            module.find('p').replaceWith(synopsis.find('p'));

            // if already visible
            if (synopsis_module.hasClass('module')) {
              synopsis_module.replaceWith(module);

            // else if not visible
            } else {
              module.hide();
              synopsis_module.replaceWith(module);
              module.fadeIn(200);
            }

          // if no synopsis
          } else {

            // if visible
            if (synopsis_module.hasClass('module')) {
              synopsis_module.fadeOut(200, function() {
                $(this).replaceWith(construct_inactive_module('synopsis', 'Synopsis'));
              });
            }
          }

        } // if synopsis module is enabled

        // trakt

        if ($('#trakt, #trakt_inactive').length > 0 && currently_playing_id !== $(data).data('id')) {
          get_module('trakt', {
            placeholder: $('#trakt_inactive')
          });
        }

        currently_playing_id = $(data).data('id');
      }
    });

    setTimeout(get_currently_playing, 5000);
  }

  if ($('body').data('show_currently_playing') === 'True') {
    get_currently_playing();
  }

  // play/pause control

  $('#currently_playing .controls .play_pause').live('click', function() {
    $.get('/xhr/controls/play_pause');
  });

  // stop control

  $('#currently_playing .controls .stop').live('click', function() {
    $.get('/xhr/controls/stop');
  });

  // click show name to view in media library module

  $('#currently_playing .item_info .show').live('click', function() {
    invoke_library('/xhr/library/shows/' + $(this).data('show'));
  });

  // click show season to view in media library module

  $('#currently_playing .item_info .season').live('click', function() {
    invoke_library('/xhr/library/shows/' + $(this).parent().find('.show').data('show') + '/' + $(this).data('season'));
  });

  function invoke_library(url) {
    $.get(url, function(data) {
      var library = $('#library');
      if (library.length > 0) {
        library.replaceWith(data);
      } else {
        $('#col1').append(data);
      }
    });
  }

  // post trakt shout

  $('#add_shout .submit').live('click', function() {
    var add_shout = $('#add_shout');
    var textarea = add_shout.find('textarea');
    var submit_wrapper = add_shout.find('.submit_wrapper');

    if (textarea.val().length === 0) {
      var error_message = submit_wrapper.find('p');

      if (error_message.length === 0) {
        submit_wrapper.append('
');
        error_message = submit_wrapper.find('p');
      }

      error_message.text('You need to enter a shout.');
      return false;
    }

    var type = add_shout.data('type');

    var dict = {
      type: type,
      itemid: add_shout.data('itemid'),
      shout: textarea.val()
    };

    if (type === 'episode') {
      dict['season'] = add_shout.data('season');
      dict['episode'] = add_shout.data('episode');
    }

    submit_wrapper.addClass('xhrloading');

    $.post('/xhr/trakt/add_shout', dict, function(data) {
      submit_wrapper.removeClass('xhrloading');
      submit_wrapper.find('p').remove();
      textarea.val('');

      if (data.status === 'error') {
        submit_wrapper.append('
There was a problem submitting your shout.
');
        return false;
      }

      if ($(data).attr('id') === 'trakt') {
        $('#trakt').replaceWith(data);
      }
    });
  });

  // view more recently added episodes

  $('#recently_added .view_older').live('click', function() {
    get_module('recently_added', {
      params: [$('#recently_added').data('offset') + $('#recently_added .episodes > li').length]
    });
    return false;
  });

  $('#recently_added .view_newer').live('click', function() {
    get_module('recently_added', {
      params: [$('#recently_added').data('offset') - $('#recently_added .episodes > li').length]
    });
    return false;
  });

  // play recently added episodes when clicking on them

  $('#recently_added li').live('click', function() {
    $.get('/xhr/play_episode/' + $(this).data('episodeid'));
  });

  // browse library

  $('#library li.get').live('click', function() {
    var url = '/xhr/library';
    var commands = $(this).data('command').split('/');

    for (var i=0; i < commands.length; i++) {
      url += '/' + commands[i];
    }

    add_loading_gif(this);

    $.get(url, function(data) {
      $('#library').replaceWith(data);
    });
  });

  $('#library li.play_episode').live('click', function() {
    var li = this;
    add_loading_gif(li);

    $.get('/xhr/play_episode/' + $(this).data('episodeid'), function() {
      remove_loading_gif(li);
    });
  });

  $('#library li.play_movie').live('click', function() {
    var li = this;
    add_loading_gif(li);

    $.get('/xhr/play_movie/' + $(this).data('movieid'), function() {
      remove_loading_gif(li);
    });
  });

  $('#library .back').live('click', function() {
    var url = '/xhr/library';
    var command = $('#library li:first-child').eq(0).data('command');

    if (command) {
      var commands = command.split('/');
      commands.pop();
      commands.pop();

      for (var i=0; i < commands.length; i++) {
        url += '/' + commands[i];
      }
    }

    $(this).addClass('xhrloading');

    $.get(url, function(data) {
      $('#library').replaceWith(data);
    });
  });

  function add_loading_gif(element) {
    $(element).append('');
  }

  function remove_loading_gif(element) {
    $(element).find('.xhrloading').remove();
  }

  // generic expand truncated text

  $('.expand').live('click', function() {
    var parent = $(this).parent();
    parent.find('.truncated').hide();
    parent.find('.expanded').show();
    $(this).hide();
    return false;
  });

  // sortable modules

  $('ul.modules').sortable({
    connectWith: 'ul.modules',
    disabled: true,
    stop: function() {
      var modules = [];

      $('.module, .inactive_module, .placeholder').each(function() {
        var position = 0;
        var li = $(this).closest('li');
        var column_ele = $(this).closest('.col');
        var lis = column_ele.find('ul.modules > li');

        for (var i = 0; i < lis.length; i++) {
          if (lis[i] == li.get(0)) {
            position = i+1;
            break;
          }
        }

        modules.push({
          name: $(this).data('module'),
          column: column_ele.attr('id').replace('col', ''),
          position: position
        });
      });

      $.post('/xhr/rearrange_modules', { modules: JSON.stringify(modules) }, function() {});
    }
  });

  // settings mode

  $('#settings_icon').live('click', function() {
    $('body').toggleClass('f_settings_mode');
    $('#tutorial').remove();

    if ($('body').hasClass('f_settings_mode')) {
      $('ul.modules').sortable({ disabled: false });
      $.get('/xhr/server_settings_dialog', function(data) {
        $('#col1 ul.modules').prepend('
' + data + '
');
      });

    } else {
      $('ul.modules').sortable({ disabled: true });
      $('.edit_settings .choices .cancel').click();
      $('#server_settings').remove();
    }
  });

  // add module

  $('.add_module').live('click', function() {
    var column = $(this).closest('.col').attr('id');
    $.get('/xhr/add_module_dialog', function(data) {
      var popup = $(data);
      $('body').append(popup);
      popup.data('col', column.replace('col', ''));
      popup.showPopup({ dispose: true });
    });
  });

  $('#add_module_dialog #select_module').live('change', function() {
    var module_description = $('#add_module_dialog .description');
    if (module_description.length === 0) {
      $('#add_module_dialog #select_module').after('
');
      module_description = $('#add_module_dialog .description');
    }
    module_description.text($(this).find(':selected').data('description'));
  });

  $('#add_module_dialog .submit').live('click', function() {
    var module_id = $('#add_module_dialog #select_module :selected').val();
    var column = $('#add_module_dialog').data('col');
    var position = $('#col' + column).find('.module, .placeholder').length + 1;

    $.post('/xhr/add_module', {
      module_id: module_id,
      column: column,
      position: position
    }, function(data) {
      $('#col' + column).find('ul.modules').append('
' + data + '
');
      init_modules();
      $('#add_module_dialog').fadeOut(300, function() {
        $(this).find('.close').click();
      });
    });
  });

  // remove module

  $('.module_remove').live('click', function() {
    var button = $(this);

    confirmation_dialog({
      question: 'Are you sure that you want to remove this module?',
      confirm: function() {
        var module = button.closest('.module, .inactive_module, .placeholder');
        $.post('/xhr/remove_module/' + module.data('module'), {}, function() {
          module.fadeOut(300, function() {
            $(this).remove();
          });
        });
      }
    });
  });

  // module settings

  $('.module_settings').live('click', function() {
    var module = $(this).closest('.module, .inactive_module, .placeholder');

    $.get('/xhr/module_settings_dialog/' + module.data('module'), function(data) {
      module.replaceWith(data);
    });
  });

  // save settings

  $('.edit_settings .choices .save').live('click', function() {
    var module = $(this).closest('.module, .inactive_module, .placeholder');
    var settings = module.find('form').serializeArray();

    $.post('/xhr/module_settings_save/' + module.data('module'),
      { settings: JSON.stringify(settings) },
      function(data) {
        module.replaceWith(data);
        init_modules();
      }
    );
  });

  // cancel settings

  $('.edit_settings .choices .cancel').live('click', function() {
    var module = $(this).closest('.module, .inactive_module, .placeholder');

    $.get('/xhr/module_settings_cancel/' + module.data('module'), function(data) {
      module.replaceWith(data);
      init_modules();
    });
  });

  // add application

  $('#add_application').live('click', function() {
    $.get('/xhr/add_application_dialog', function(data) {
      var popup = $(data);
      $('body').append(popup);
      popup.showPopup({ dispose: true });
    });
  });

});<commit_msg>stop server settings from potentially appearing multiple times<commit_after>$(document).ready(function() {

  // helper functions

  var settings_buttons = '
Settings

Remove
';

  function construct_inactive_module(name, title) {
    return '
' + settings_buttons + '
' + title + '

';
  }

  function confirmation_dialog(customsettings) {
    var settings = {
      question: 'Are you sure?',
      confirm: function() {},
      cancel: function() {}
    };

    if (customsettings !== undefined) {
      $.extend(settings, customsettings);
    }

    var dialog = '

' + settings.question + '

Yes

No

';

    $('body').append(dialog);

    $('#confirmation_dialog').showPopup({
      dispose: true,
      on_confirm: settings.confirm,
      on_close: settings.cancel
    });
  }

  // get/poll module

  function get_module(module, customsettings) {
    var settings = {
      poll: 0,
      placeholder: $('.placeholder[data-module=' + module + ']'),
      params: []
    }

    if (customsettings !== undefined) {
      $.extend(settings, customsettings);
    }

    var url = '/xhr/' + module;

    for (var i=0; i < settings.params.length; i++) {
      url += '/' + settings.params[i];
    }

    $.get(url, function(data) {
      var module_ele = $('#' + module);

      // if module is already on page
      if (module_ele.length > 0) {

        // if module has been returned by the XHR view
        if ($(data).attr('id') === module) {
          module_ele.replaceWith(data);

        // else placeholder has been returned by the XHR view
        } else {
          module_ele.fadeOut(200, function() {
            $(this).replaceWith(data);
          });
        }

      // placeholder is on page
      } else {
        var new_module = $(data).hide();
        settings.placeholder.replaceWith(new_module);
        $('.module[data-module=' + module + ']').fadeIn(200);
      }
    });

    // poll
    if (settings.poll !== 0) {
      setTimeout(function() {
        get_module(module, {
          poll: settings.poll
        })
      }, settings.poll * 1000);
    }
  }

  // initialise modules on page load

  function init_modules() {
    $('.placeholder:not(.initialised)').each(function() {
      $(this).addClass('initialised');
      var delay = $(this).data('delay');
      if (delay === undefined) {
        get_module($(this).data('module'), {
          poll: $(this).data('poll')
        });
      } else {
        var module = $(this).data('module');
        var poll = $(this).data('poll');
        setTimeout(function() {
          get_module(module, {
            poll: poll
          });
        }, delay * 1000);
      }
    });
  }

  init_modules();

  // currently playing

  var currently_playing_id = null;

  function get_currently_playing() {
    $.get('/xhr/currently_playing', function(data) {

      if (data.playing === false) {

        // hide currently playing
        $('#currently_playing').slideUp(200, function() {
          $(this).remove();
        });

        // hide synopsis module if visible
        $('#synopsis').fadeOut(200, function() {
          $(this).replaceWith(construct_inactive_module('synopsis', 'Synopsis'));
        });

        // hide trakt module if visible
        $('#trakt').fadeOut(200, function() {
          $(this).replaceWith(construct_inactive_module('trakt', 'trakt.tv'));
        });

        currently_playing_id = null;

      } else {
        var currently_playing_module = $('#currently_playing');

        if (currently_playing_module.length > 0) {
          currently_playing_module.replaceWith(data);

        } else {
          var module = $(data).hide();
          $('body').append(module);
          $('#currently_playing').slideDown(200);
        }

        // use fanart of currently playing item as background if enabled in settings

        if ($('body').data('fanart_backgrounds') === 'True') {
          var fanart_url = $('#currently_playing').data('fanart');
          if (fanart_url !== undefined) {
            var img = new Image();
            img.onload = function() {
              var fanart = $('#fanart');
              fanart.css('background-image', 'url(' + fanart_url + ')');
              if (!fanart.is(':visible')) {
                fanart.fadeIn(500);
              }
            };
            img.src = fanart_url;
          }
        }

        // synopsis

        // if synopsis module is enabled
        var synopsis_module = $('#synopsis, #synopsis_inactive');
        if (synopsis_module.length > 0) {

          // if currently playing item has a synopsis
          var synopsis = $('#currently_playing .synopsis');
          if (synopsis.length > 0) {
            var module = $('
' + settings_buttons + '

');
            module.find('h2').replaceWith(synopsis.find('h2'));
            module.find('p').replaceWith(synopsis.find('p'));

            // if already visible
            if (synopsis_module.hasClass('module')) {
              synopsis_module.replaceWith(module);

            // else if not visible
            } else {
              module.hide();
              synopsis_module.replaceWith(module);
              module.fadeIn(200);
            }

          // if no synopsis
          } else {

            // if visible
            if (synopsis_module.hasClass('module')) {
              synopsis_module.fadeOut(200, function() {
                $(this).replaceWith(construct_inactive_module('synopsis', 'Synopsis'));
              });
            }
          }

        } // if synopsis module is enabled

        // trakt

        if ($('#trakt, #trakt_inactive').length > 0 && currently_playing_id !== $(data).data('id')) {
          get_module('trakt', {
            placeholder: $('#trakt_inactive')
          });
        }

        currently_playing_id = $(data).data('id');
      }
    });

    setTimeout(get_currently_playing, 5000);
  }

  if ($('body').data('show_currently_playing') === 'True') {
    get_currently_playing();
  }

  // play/pause control

  $('#currently_playing .controls .play_pause').live('click', function() {
    $.get('/xhr/controls/play_pause');
  });

  // stop control

  $('#currently_playing .controls .stop').live('click', function() {
    $.get('/xhr/controls/stop');
  });

  // click show name to view in media library module

  $('#currently_playing .item_info .show').live('click', function() {
    invoke_library('/xhr/library/shows/' + $(this).data('show'));
  });

  // click show season to view in media library module

  $('#currently_playing .item_info .season').live('click', function() {
    invoke_library('/xhr/library/shows/' + $(this).parent().find('.show').data('show') + '/' + $(this).data('season'));
  });

  function invoke_library(url) {
    $.get(url, function(data) {
      var library = $('#library');
      if (library.length > 0) {
        library.replaceWith(data);
      } else {
        $('#col1').append(data);
      }
    });
  }

  // post trakt shout

  $('#add_shout .submit').live('click', function() {
    var add_shout = $('#add_shout');
    var textarea = add_shout.find('textarea');
    var submit_wrapper = add_shout.find('.submit_wrapper');

    if (textarea.val().length === 0) {
      var error_message = submit_wrapper.find('p');

      if (error_message.length === 0) {
        submit_wrapper.append('
');
        error_message = submit_wrapper.find('p');
      }

      error_message.text('You need to enter a shout.');
      return false;
    }

    var type = add_shout.data('type');

    var dict = {
      type: type,
      itemid: add_shout.data('itemid'),
      shout: textarea.val()
    };

    if (type === 'episode') {
      dict['season'] = add_shout.data('season');
      dict['episode'] = add_shout.data('episode');
    }

    submit_wrapper.addClass('xhrloading');

    $.post('/xhr/trakt/add_shout', dict, function(data) {
      submit_wrapper.removeClass('xhrloading');
      submit_wrapper.find('p').remove();
      textarea.val('');

      if (data.status === 'error') {
        submit_wrapper.append('
There was a problem submitting your shout.
');
        return false;
      }

      if ($(data).attr('id') === 'trakt') {
        $('#trakt').replaceWith(data);
      }
    });
  });

  // view more recently added episodes

  $('#recently_added .view_older').live('click', function() {
    get_module('recently_added', {
      params: [$('#recently_added').data('offset') + $('#recently_added .episodes > li').length]
    });
    return false;
  });

  $('#recently_added .view_newer').live('click', function() {
    get_module('recently_added', {
      params: [$('#recently_added').data('offset') - $('#recently_added .episodes > li').length]
    });
    return false;
  });

  // play recently added episodes when clicking on them

  $('#recently_added li').live('click', function() {
    $.get('/xhr/play_episode/' + $(this).data('episodeid'));
  });

  // browse library

  $('#library li.get').live('click', function() {
    var url = '/xhr/library';
    var commands = $(this).data('command').split('/');

    for (var i=0; i < commands.length; i++) {
      url += '/' + commands[i];
    }

    add_loading_gif(this);

    $.get(url, function(data) {
      $('#library').replaceWith(data);
    });
  });

  $('#library li.play_episode').live('click', function() {
    var li = this;
    add_loading_gif(li);

    $.get('/xhr/play_episode/' + $(this).data('episodeid'), function() {
      remove_loading_gif(li);
    });
  });

  $('#library li.play_movie').live('click', function() {
    var li = this;
    add_loading_gif(li);

    $.get('/xhr/play_movie/' + $(this).data('movieid'), function() {
      remove_loading_gif(li);
    });
  });

  $('#library .back').live('click', function() {
    var url = '/xhr/library';
    var command = $('#library li:first-child').eq(0).data('command');

    if (command) {
      var commands = command.split('/');
      commands.pop();
      commands.pop();

      for (var i=0; i < commands.length; i++) {
        url += '/' + commands[i];
      }
    }

    $(this).addClass('xhrloading');

    $.get(url, function(data) {
      $('#library').replaceWith(data);
    });
  });

  function add_loading_gif(element) {
    $(element).append('');
  }

  function remove_loading_gif(element) {
    $(element).find('.xhrloading').remove();
  }

  // generic expand truncated text

  $('.expand').live('click', function() {
    var parent = $(this).parent();
    parent.find('.truncated').hide();
    parent.find('.expanded').show();
    $(this).hide();
    return false;
  });

  // sortable modules

  $('ul.modules').sortable({
    connectWith: 'ul.modules',
    disabled: true,
    stop: function() {
      var modules = [];

      $('.module, .inactive_module, .placeholder').each(function() {
        var position = 0;
        var li = $(this).closest('li');
        var column_ele = $(this).closest('.col');
        var lis = column_ele.find('ul.modules > li');

        for (var i = 0; i < lis.length; i++) {
          if (lis[i] == li.get(0)) {
            position = i+1;
            break;
          }
        }

        modules.push({
          name: $(this).data('module'),
          column: column_ele.attr('id').replace('col', ''),
          position: position
        });
      });

      $.post('/xhr/rearrange_modules', { modules: JSON.stringify(modules) }, function() {});
    }
  });

  // settings mode

  $('#settings_icon').live('click', function() {
    $('body').toggleClass('f_settings_mode');
    $('#tutorial').remove();

    if ($('body').hasClass('f_settings_mode')) {
      $('ul.modules').sortable({ disabled: false });
      $.get('/xhr/server_settings_dialog', function(data) {
        var existing_server_settings = $('#server_settings').closest('li');

        if (existing_server_settings.length === 0) {
          var existing_server_settings = $('#col1 ul.modules').prepend('
').find('li:first-child');
        }

        existing_server_settings.empty().append(data);
      });

    } else {
      $('ul.modules').sortable({ disabled: true });
      $('.edit_settings .choices .cancel').click();
      $('#server_settings').closest('li').remove();
    }
  });

  // add module

  $('.add_module').live('click', function() {
    var column = $(this).closest('.col').attr('id');
    $.get('/xhr/add_module_dialog', function(data) {
      var popup = $(data);
      $('body').append(popup);
      popup.data('col', column.replace('col', ''));
      popup.showPopup({ dispose: true });
    });
  });

  $('#add_module_dialog #select_module').live('change', function() {
    var module_description = $('#add_module_dialog .description');
    if (module_description.length === 0) {
      $('#add_module_dialog #select_module').after('
');
      module_description = $('#add_module_dialog .description');
    }
    module_description.text($(this).find(':selected').data('description'));
  });

  $('#add_module_dialog .submit').live('click', function() {
    var module_id = $('#add_module_dialog #select_module :selected').val();
    var column = $('#add_module_dialog').data('col');
    var position = $('#col' + column).find('.module, .placeholder').length + 1;

    $.post('/xhr/add_module', {
      module_id: module_id,
      column: column,
      position: position
    }, function(data) {
      $('#col' + column).find('ul.modules').append('
' + data + '
');
      init_modules();
      $('#add_module_dialog').fadeOut(300, function() {
        $(this).find('.close').click();
      });
    });
  });

  // remove module

  $('.module_remove').live('click', function() {
    var button = $(this);

    confirmation_dialog({
      question: 'Are you sure that you want to remove this module?',
      confirm: function() {
        var module = button.closest('.module, .inactive_module, .placeholder');
        $.post('/xhr/remove_module/' + module.data('module'), {}, function() {
          module.fadeOut(300, function() {
            $(this).remove();
          });
        });
      }
    });
  });

  // module settings

  $('.module_settings').live('click', function() {
    var module = $(this).closest('.module, .inactive_module, .placeholder');

    $.get('/xhr/module_settings_dialog/' + module.data('module'), function(data) {
      module.replaceWith(data);
    });
  });

  // save settings

  $('.edit_settings .choices .save').live('click', function() {
    var module = $(this).closest('.module, .inactive_module, .placeholder');
    var settings = module.find('form').serializeArray();

    $.post('/xhr/module_settings_save/' + module.data('module'),
      { settings: JSON.stringify(settings) },
      function(data) {
        module.replaceWith(data);
        init_modules();
      }
    );
  });

  // cancel settings

  $('.edit_settings .choices .cancel').live('click', function() {
    var module = $(this).closest('.module, .inactive_module, .placeholder');

    $.get('/xhr/module_settings_cancel/' + module.data('module'), function(data) {
      module.replaceWith(data);
      init_modules();
    });
  });

  // add application

  $('#add_application').live('click', function() {
    $.get('/xhr/add_application_dialog', function(data) {
      var popup = $(data);
      $('body').append(popup);
      popup.showPopup({ dispose: true });
    });
  });

});<|endoftext|>


<commit_before>import clickThis from '../common/clickThis';
import createTextArea from '../common/cElement/createTextArea';
import getArrayByTagName from '../common/getArrayByTagName';
import getElementsByTagName from '../common/getElementsByTagName';
import getValue from '../system/getValue';
import insertElement from '../common/insertElement';
import on from '../common/on';
import { pCC } from '../support/layout';
import partial from '../common/partial';
import querySelector from '../common/querySelector';

function removeCrlf(fshTxt) {
  // eslint-disable-next-line no-param-reassign
  fshTxt.value = fshTxt.value.replace(/\r\n|\n|\r/g, ' ');
}

function setDoChat(el) {
  el.setAttribute('form', 'dochat');
}

function giveFormId() {
  const formList = getElementsByTagName('form', pCC);
  formList[0].id = 'dochat';
  return formList[0];
}

function giveInputsId() {
  const filteredList = getArrayByTagName('input', pCC).slice(0, 7);
  filteredList.forEach(setDoChat);
  return filteredList[5];
}

function rearrangeTable(btnMass) {
  const theTable = querySelector('#pCC table table');
  theTable.rows[0].cells[0].remove();
  const myCell = theTable.insertRow(-1).insertCell(-1);
  insertElement(myCell, btnMass);
  const ourTd = theTable.rows[0].cells[0];
  ourTd.rowSpan = 2;
  return ourTd;
}

function keypress(sendBtn, evt) {
  if (evt.key === 'Enter' && !evt.shiftKey) {
    evt.preventDefault();
    clickThis(sendBtn);
  }
}

function makeTextArea(sendBtn) {
  const fshTxt = createTextArea({
    cols: 72,
    name: 'msg',
    required: true,
    rows: 2,
  });
  setDoChat(fshTxt);
  on(fshTxt, 'keypress', partial(keypress, sendBtn));
  return fshTxt;
}

function hasTextEntry() {
  const btnMass = querySelector('input[value="Send As Mass"]');
  if (!btnMass) { return; }
  const theForm = giveFormId();
  const sendBtn = giveInputsId();
  const ourTd = rearrangeTable(btnMass);
  const fshTxt = makeTextArea(sendBtn);
  ourTd.replaceChild(fshTxt, ourTd.children[0]);
  on(theForm, 'submit', partial(removeCrlf, fshTxt));
}

export default function addChatTextArea() {
  if (!getValue('enhanceChatTextEntry') || !pCC) { return; }
  hasTextEntry();
}
<commit_msg>maxLength for enhanced chat entry<commit_after>import clickThis from '../common/clickThis';
import createTextArea from '../common/cElement/createTextArea';
import getArrayByTagName from '../common/getArrayByTagName';
import getElementsByTagName from '../common/getElementsByTagName';
import getValue from '../system/getValue';
import insertElement from '../common/insertElement';
import on from '../common/on';
import { pCC } from '../support/layout';
import partial from '../common/partial';
import querySelector from '../common/querySelector';

function removeCrlf(fshTxt) {
  // eslint-disable-next-line no-param-reassign
  fshTxt.value = fshTxt.value.replace(/\r\n|\n|\r/g, ' ');
}

function setDoChat(el) {
  el.setAttribute('form', 'dochat');
}

function giveFormId() {
  const formList = getElementsByTagName('form', pCC);
  formList[0].id = 'dochat';
  return formList[0];
}

function giveInputsId() {
  const filteredList = getArrayByTagName('input', pCC).slice(0, 7);
  filteredList.forEach(setDoChat);
  return filteredList[5];
}

function rearrangeTable(btnMass) {
  const theTable = querySelector('#pCC table table');
  theTable.rows[0].cells[0].remove();
  const myCell = theTable.insertRow(-1).insertCell(-1);
  insertElement(myCell, btnMass);
  const ourTd = theTable.rows[0].cells[0];
  ourTd.rowSpan = 2;
  return ourTd;
}

function keypress(sendBtn, evt) {
  if (evt.key === 'Enter' && !evt.shiftKey) {
    evt.preventDefault();
    clickThis(sendBtn);
  }
}

function makeTextArea(sendBtn) {
  const fshTxt = createTextArea({
    cols: 72,
    maxLength: 512,
    name: 'msg',
    required: true,
    rows: 2,
  });
  setDoChat(fshTxt);
  on(fshTxt, 'keypress', partial(keypress, sendBtn));
  return fshTxt;
}

function hasTextEntry() {
  const btnMass = querySelector('input[value="Send As Mass"]');
  if (!btnMass) { return; }
  const theForm = giveFormId();
  const sendBtn = giveInputsId();
  const ourTd = rearrangeTable(btnMass);
  const fshTxt = makeTextArea(sendBtn);
  ourTd.replaceChild(fshTxt, ourTd.children[0]);
  on(theForm, 'submit', partial(removeCrlf, fshTxt));
}

export default function addChatTextArea() {
  if (!getValue('enhanceChatTextEntry') || !pCC) { return; }
  hasTextEntry();
}
<|endoftext|>