diff --git a/lsp/functions.js b/lsp/functions.js index 56427740..aed0861b 100644 --- a/lsp/functions.js +++ b/lsp/functions.js @@ -390,8 +390,10 @@ "log": {}, "statistics": {} }, d) - if (settings.settings.LTS != 1) { - $('.LTSonly').remove(); + if (settings.settings.LTS == 1) { + $('.LTSonly').show(); + } else { + $('.LTSonly').hide(); } } if(callback) @@ -460,4 +462,517 @@ } } } +/** + * Build a HTML limit row + * @param l the limit data + * @return a (jQuery'd) HTML Element + */ +function BuildLimitRow(l) +{ + l['type'] = l['type'] || 'soft'; + l['name'] = l['name'] || 'kb_total'; + l['val'] = l['val'] || 0; + var i, j, lv, db, + output = $("<tr>").addClass("limits_row"), + selects = [$("<select class=\"limits_type\">"), $("<select class=\"limits_name\">")], + options = + [ + [ + ['soft', 'Softlimit', 'Allow this limit to be passed. (Usefull for alerts)'], + ['hard', 'Hardlimit','Do not allow this limit to be passed.'] + ], + [ + ['kb_total', 'Total bandwidth','Total bandwidth in bytes.'], + ['kbps_max', 'Current bandwidth', 'Current bandwidth in bytes/s.'], + ['users', 'Concurrent users','Maximum concurrent users.'], + ['geo', 'Geolimited', 'Either a blacklist or whitelist containing country codes.'], + ['host', 'Hostlimited', 'Either a blacklist or whitelist containing hosts seperated by spaces.'], + ], + ['type', 'name'] + ]; + /* + Limits that are currently not in use but may return later: + ['duration', 'Duration', 'Maximum duration a user may be connected in seconds.'], + ['str_kbps_min', 'Minimum bitrate','Minimum bitrate in bytes/s.'], + ['str_kbps_max', 'Maximum bitrate','Maximum bitrate in bytes/s.'] + */ + + for(i = 0; i < 2; i++) + { + + for(j = 0; j < options[i].length; j++) + { + selects[i].append( + $('<option>').val(options[i][j][0]).text(options[i][j][1]).data('desc',options[i][j][2]) + ); + } + + selects[i].val(l[options[2][i]]).change(function(){ + removeTooltip(); + var pos = $(this).offset(); + showTooltip({'pageX':pos.left,'pageY':pos.top+16},undefined,$(this).children(':selected').data('desc')); + $(this).parents('.limits_row').children('.limit_input_container').html(''); + BuildLimitRowInput( + $(this).parents('.limits_row').children('.limit_input_container'), + { + 'name':$(this).parents('.limits_row').find(".limits_name").val(), + 'type':$(this).parents('.limits_row').find(".limits_type").val(), + 'val':$(this).parents('.limits_row').find(".limits_val").val() + } + ); + }).focus(function(){ + var pos = $(this).offset(); + showTooltip({'pageX':pos.left,'pageY':pos.top+16},undefined,$(this).children(':selected').data('desc')); + }).blur(function(){ + removeTooltip(); + }); + output.append($('<td>').html(selects[i])); + } + + lv = $('<td>').addClass('limit_input_container'); + BuildLimitRowInput(lv,l); + + appliesto = $('<td>'); + var appliesselect = $('<select>').attr('class', 'new-limit-appliesto').append( $('<option>').attr('value', 'server').text('Server') ); + for(var strm in settings.settings.streams) { + appliesselect.append( + $('<option>').attr('value', strm).text(settings.settings.streams[strm].name) + ); + } + if (l.appliesto) { + appliesselect.val(l.appliesto); + } + appliesto.append(appliesselect); + + + + db = $('<td>').html( + $('<button>').addClass('limit_delete_button').text('Delete').click(function(){$(this).parent().parent().remove();}) + ); + + output.append(lv).append(appliesto).append(db); + + return output; +} + + + +/** + * Build a HTML limit row input field + * @param target where the input field should be inserted + * @param l the limit data + */ + function BuildLimitRowInput(target,l) { + if (!l.val) { l.val=0; } + switch (l.name) { + case 'geo': + var countrylist = [ + ['AF','Afghanistan'], + ['AX','�land Islands'], + ['AL','Albania'], + ['DZ','Algeria'], + ['AS','American Samoa'], + ['AD','Andorra'], + ['AO','Angola'], + ['AI','Anguilla'], + ['AQ','Antarctica'], + ['AG','Antigua and Barbuda'], + ['AR','Argentina'], + ['AM','Armenia'], + ['AW','Aruba'], + ['AU','Australia'], + ['AT','Austria'], + ['AZ','Azerbaijan'], + ['BS','Bahamas'], + ['BH','Bahrain'], + ['BD','Bangladesh'], + ['BB','Barbados'], + ['BY','Belarus'], + ['BE','Belgium'], + ['BZ','Belize'], + ['BJ','Benin'], + ['BM','Bermuda'], + ['BT','Bhutan'], + ['BO','Bolivia, Plurinational State of'], + ['BQ','Bonaire, Sint Eustatius and Saba'], + ['BA','Bosnia and Herzegovina'], + ['BW','Botswana'], + ['BV','Bouvet Island'], + ['BR','Brazil'], + ['IO','British Indian Ocean Territory'], + ['BN','Brunei Darussalam'], + ['BG','Bulgaria'], + ['BF','Burkina Faso'], + ['BI','Burundi'], + ['KH','Cambodia'], + ['CM','Cameroon'], + ['CA','Canada'], + ['CV','Cape Verde'], + ['KY','Cayman Islands'], + ['CF','Central African Republic'], + ['TD','Chad'], + ['CL','Chile'], + ['CN','China'], + ['CX','Christmas Island'], + ['CC','Cocos (Keeling) Islands'], + ['CO','Colombia'], + ['KM','Comoros'], + ['CG','Congo'], + ['CD','Congo, the Democratic Republic of the'], + ['CK','Cook Islands'], + ['CR','Costa Rica'], + ['CI','C�te d\'Ivoire'], + ['HR','Croatia'], + ['CU','Cuba'], + ['CW','Cura�ao'], + ['CY','Cyprus'], + ['CZ','Czech Republic'], + ['DK','Denmark'], + ['DJ','Djibouti'], + ['DM','Dominica'], + ['DO','Dominican Republic'], + ['EC','Ecuador'], + ['EG','Egypt'], + ['SV','El Salvador'], + ['GQ','Equatorial Guinea'], + ['ER','Eritrea'], + ['EE','Estonia'], + ['ET','Ethiopia'], + ['FK','Falkland Islands (Malvinas)'], + ['FO','Faroe Islands'], + ['FJ','Fiji'], + ['FI','Finland'], + ['FR','France'], + ['GF','French Guiana'], + ['PF','French Polynesia'], + ['TF','French Southern Territories'], + ['GA','Gabon'], + ['GM','Gambia'], + ['GE','Georgia'], + ['DE','Germany'], + ['GH','Ghana'], + ['GI','Gibraltar'], + ['GR','Greece'], + ['GL','Greenland'], + ['GD','Grenada'], + ['GP','Guadeloupe'], + ['GU','Guam'], + ['GT','Guatemala'], + ['GG','Guernsey'], + ['GN','Guinea'], + ['GW','Guinea-Bissau'], + ['GY','Guyana'], + ['HT','Haiti'], + ['HM','Heard Island and McDonald Islands'], + ['VA','Holy See (Vatican City State)'], + ['HN','Honduras'], + ['HK','Hong Kong'], + ['HU','Hungary'], + ['IS','Iceland'], + ['IN','India'], + ['ID','Indonesia'], + ['IR','Iran, Islamic Republic of'], + ['IQ','Iraq'], + ['IE','Ireland'], + ['IM','Isle of Man'], + ['IL','Israel'], + ['IT','Italy'], + ['JM','Jamaica'], + ['JP','Japan'], + ['JE','Jersey'], + ['JO','Jordan'], + ['KZ','Kazakhstan'], + ['KE','Kenya'], + ['KI','Kiribati'], + ['KP','Korea, Democratic People\'s Republic of'], + ['KR','Korea, Republic of'], + ['KW','Kuwait'], + ['KG','Kyrgyzstan'], + ['LA','Lao People\'s Democratic Republic'], + ['LV','Latvia'], + ['LB','Lebanon'], + ['LS','Lesotho'], + ['LR','Liberia'], + ['LY','Libya'], + ['LI','Liechtenstein'], + ['LT','Lithuania'], + ['LU','Luxembourg'], + ['MO','Macao'], + ['MK','Macedonia, the former Yugoslav Republic of'], + ['MG','Madagascar'], + ['MW','Malawi'], + ['MY','Malaysia'], + ['MV','Maldives'], + ['ML','Mali'], + ['MT','Malta'], + ['MH','Marshall Islands'], + ['MQ','Martinique'], + ['MR','Mauritania'], + ['MU','Mauritius'], + ['YT','Mayotte'], + ['MX','Mexico'], + ['FM','Micronesia, Federated States of'], + ['MD','Moldova, Republic of'], + ['MC','Monaco'], + ['MN','Mongolia'], + ['ME','Montenegro'], + ['MS','Montserrat'], + ['MA','Morocco'], + ['MZ','Mozambique'], + ['MM','Myanmar'], + ['NA','Namibia'], + ['NR','Nauru'], + ['NP','Nepal'], + ['NL','Netherlands'], + ['NC','New Caledonia'], + ['NZ','New Zealand'], + ['NI','Nicaragua'], + ['NE','Niger'], + ['NG','Nigeria'], + ['NU','Niue'], + ['NF','Norfolk Island'], + ['MP','Northern Mariana Islands'], + ['NO','Norway'], + ['OM','Oman'], + ['PK','Pakistan'], + ['PW','Palau'], + ['PS','Palestine, State of'], + ['PA','Panama'], + ['PG','Papua New Guinea'], + ['PY','Paraguay'], + ['PE','Peru'], + ['PH','Philippines'], + ['PN','Pitcairn'], + ['PL','Poland'], + ['PT','Portugal'], + ['PR','Puerto Rico'], + ['QA','Qatar'], + ['RE','R�union'], + ['RO','Romania'], + ['RU','Russian Federation'], + ['RW','Rwanda'], + ['BL','Saint Barth�lemy'], + ['SH','Saint Helena, Ascension and Tristan da Cunha'], + ['KN','Saint Kitts and Nevis'], + ['LC','Saint Lucia'], + ['MF','Saint Martin (French part)'], + ['PM','Saint Pierre and Miquelon'], + ['VC','Saint Vincent and the Grenadines'], + ['WS','Samoa'], + ['SM','San Marino'], + ['ST','Sao Tome and Principe'], + ['SA','Saudi Arabia'], + ['SN','Senegal'], + ['RS','Serbia'], + ['SC','Seychelles'], + ['SL','Sierra Leone'], + ['SG','Singapore'], + ['SX','Sint Maarten (Dutch part)'], + ['SK','Slovakia'], + ['SI','Slovenia'], + ['SB','Solomon Islands'], + ['SO','Somalia'], + ['ZA','South Africa'], + ['GS','South Georgia and the South Sandwich Islands'], + ['SS','South Sudan'], + ['ES','Spain'], + ['LK','Sri Lanka'], + ['SD','Sudan'], + ['SR','Suriname'], + ['SJ','Svalbard and Jan Mayen'], + ['SZ','Swaziland'], + ['SE','Sweden'], + ['CH','Switzerland'], + ['SY','Syrian Arab Republic'], + ['TW','Taiwan, Province of China'], + ['TJ','Tajikistan'], + ['TZ','Tanzania, United Republic of'], + ['TH','Thailand'], + ['TL','Timor-Leste'], + ['TG','Togo'], + ['TK','Tokelau'], + ['TO','Tonga'], + ['TT','Trinidad and Tobago'], + ['TN','Tunisia'], + ['TR','Turkey'], + ['TM','Turkmenistan'], + ['TC','Turks and Caicos Islands'], + ['TV','Tuvalu'], + ['UG','Uganda'], + ['UA','Ukraine'], + ['AE','United Arab Emirates'], + ['GB','United Kingdom'], + ['US','United States'], + ['UM','United States Minor Outlying Islands'], + ['UY','Uruguay'], + ['UZ','Uzbekistan'], + ['VU','Vanuatu'], + ['VE','Venezuela, Bolivarian Republic of'], + ['VN','Viet Nam'], + ['VG','Virgin Islands, British'], + ['VI','Virgin Islands, U.S.'], + ['WF','Wallis and Futuna'], + ['EH','Western Sahara'], + ['YE','Yemen'], + ['ZM','Zambia'], + ['ZW','Zimbabwe'] + ]; + var entrylist = l.val.toString(); + + //build the template country selectbox + var geoselect = $('<select>').addClass('limit_listentry'); + geoselect.append( + $('<option>').val('').text('[Select a country]') + ); + for (i in countrylist) { + geoselect.append( + $('<option>').val(countrylist[i][0]).text(countrylist[i][1]) + ); + } + + //build the blacklist or whitelist selectbox + var selectbox = $('<select>').addClass('limit_listtype'); + if (entrylist.charAt(0) == '+') { + selectbox.html($('<option>').val('+').text('Whitelist')); + } + else { + selectbox.html($('<option>').val('-').text('Blacklist')); + } + selectbox.append($('<option>').val('-').text('Blacklist')); + selectbox.append($('<option>').val('+').text('Whitelist')); + var inputfields = $('<table>').addClass('limit_inputfields').append( + $('<tbody>').append( + $('<tr>').append( + $('<td>').append( + selectbox + ) + ) + ) + ); + entrylist = entrylist.substring(1).split(' '); + + var firstfieldused = false; + //insert selectboxes with currently set geolimits + for (i in entrylist) { + if (entrylist[i] == "") { continue; } + //make a new country selectbox based on the template + var newgeoselect = geoselect.clone(); + var code = entrylist[i]; + var country = '[Country code not recognized]'; + for (j in countrylist) { + if (countrylist[j][0] == code) { + country = countrylist[j][1]; + break; + } + } + newgeoselect.prepend($('<option>').val(code).text(country)); + + if (firstfieldused) { + inputfields.children('tbody').append( + $('<tr>').append( + $('<td>') + ).append( + $('<td>').html(newgeoselect) + ) + ); + } + else { + inputfields.children('tbody').children('tr').append( + $('<td>').html(newgeoselect) + ); + firstfieldused = true; + } + } + if (!firstfieldused) { + inputfields.children('tbody').children('tr').append( + $('<td>').html(geoselect.clone()) + ); + } + + //add a button to insert country selectboxes + var addbutton = $('<button>').text('Add country selectbox').click(function(){ + $(this).parent('td').parent('tr').before( + $('<tr>').append( + $('<td>') + ).append( + $('<td>').html(geoselect.clone()) + ) + ) + }); + + inputfields.children('tbody').append( + $('<tr>').append( + $('<td>') + ).append( + $('<td>').html(addbutton) + ) + ); + + target.html(inputfields); + break; + case 'host': + case 'time': + var entrylist = l.val.toString(); + + //add blacklist/whitelist select box + var selectbox = $('<select>').addClass('limit_listtype'); + if (entrylist.charAt(0) == '+') { + selectbox.html($('<option>').val('+').text('Whitelist')); + } + else { + selectbox.html($('<option>').val('-').text('Blacklist')); + } + selectbox.append($('<option>').val('-').text('Blacklist')); + selectbox.append($('<option>').val('+').text('Whitelist')); + target.html( + $('<span>').addClass('limit_inputfields').append( + selectbox + ) + ); + entrylist = entrylist.substring(1); + + //add inputfield + target.children('.limit_inputfields').append( + $('<input>').attr('type','text').addClass('limit_listentry').val(entrylist) + ); + break; + default: + target.html($("<input type=\"text\" class=\"limits_val\">").val(l["val"])); + break; + } +} + +/** + * Tooltip creator - creates a tooltip near the cursor + @params: - position: the object returned by the hover or click event + - appendto: the jquery element to which the tooltip should be appended + - contents: the content of the tooltip + */ +function showTooltip(position,appendto,contents,debug) { + if (position == null) { position = { pageX: 0, pageY:0 } } + if (appendto == null) { appendto = $('body'); } + if (contents == null) { contents = 'Empty'; } + var css = {}; + if (position.pageX > window.innerWidth / 2) { + css.right = appendto.offset().left + appendto.width() - position.pageX + 10; + } + else { + css.left = position.pageX - appendto.offset().left + 10; + } + if (position.pageY > window.innerHeight / 2) { + css.bottom = appendto.offset().top + appendto.height() - position.pageY + 10; + } + else { + css.top = position.pageY - appendto.offset().top + 10; + } + $("<div>").attr('id','tooltip').html( + contents + ).css(css).appendTo(appendto).fadeIn("fast"); + if (debug) { console.log('Tooltip.. position:',position,'appendto:',appendto,'contents:',contents,'css:',css); } +} +function removeTooltip() { + $('#tooltip').fadeOut("fast",function(){ + $('#tooltip').remove(); + }); +} \ No newline at end of file diff --git a/lsp/main.js b/lsp/main.js index e6dfc978..82f0be7d 100644 --- a/lsp/main.js +++ b/lsp/main.js @@ -1060,7 +1060,7 @@ } $table = $('<table>'); - $table.html("<thead><th>Type</th><th>Hard/soft</th><th>Value</th><th>applies to</th><th>Action</th></thead>"); + $table.html("<thead><th>Hard/soft</th><th>Type</th><th>Value</th><th>Applies to</th><th>Action</th></thead>"); $tbody = $('<tbody>'); var i, tr, limit, stream, clims, @@ -1084,108 +1084,70 @@ // remove old items $tbody.html(''); + //build current limits for(i = 0; i < len; i++) { - tr = $('<tr>').attr('id', 'limits-' + i); limit = alllimits[i]; - - tr.append( $('<td>').text( shortToLongLimit(limit.name) ) ); - tr.append( $('<td>').text( limit.type ) ); - tr.append( $('<td>').text( limit.val ) ); - - if(limit.appliesto) - { - tr.append( $('<td>').text( settings.settings.streams[limit.appliesto].name ).attr('id', 'limit-at-' + limit.appliesto + '-' + limit.appliesi) ); - }else{ - tr.append( $('<td>').text( 'server' ) ); - } - - delete limit.appliesto; - delete limit.appliesi; - - tr.append( $('<td>').attr('class', 'center').append( $('<button>').click(function() - { - if(confirmDelete('Are you sure you want to delete this limit?') == true) - { - var id = $(this).parent().parent().attr('id').replace('limits-', ''); - var at = $($(this).parent().parent().children()[3]).attr('id'); - - if(at == undefined) - { - settings.settings.config.limits.splice(id, 1); - }else{ - var data = at.replace('limit-at-', '').split('-'); - var loc = data.pop(); - data = data.join('-'); - - settings.settings.streams[data].limits.splice(loc, 1); - } - - $(this).parent().parent().remove(); - - loadSettings(); - } - }).text('delete') ) ); - - $tbody.append(tr); + $tbody.append(BuildLimitRow(limit)); } - - // add new limit - $nltr = $('<tr>').attr('class', 'outsidetable'); - - // type selector - $ltype = $('<select>').attr('id', 'new-limit-type'); - for(i = 0; i < ltypes.length; i++) - { - $ltype.append( $('<option>').attr('value', ltypes[i][0]).text(ltypes[i][1]) ); - } - $nltr.append( $('<td>').append( $ltype ) ); - // hard/soft limit - $nltr.append( $('<td>').append( $('<select>').attr('id', 'new-limit-hs').append( $('<option>').attr('value', 'hard').text('Hard limit') ).append( $('<option>').attr('value', 'soft').text('Soft limit') ) ) ); - // value - $nltr.append( $('<td>').append( $('<input>').attr('type', 'text').attr('id', 'new-limit-val') ) ); - - // applies to (stream) - var $appliesto = $('<select>').attr('id', 'new-limit-appliesto').append( $('<option>').attr('value', 'server').text('Server') ); - - for(var strm in settings.settings.streams) - { - $appliesto.append( - $('<option>').attr('value', strm).text(settings.settings.streams[strm].name) - ); - } - $nltr.append( $('<td>').append( $appliesto ) ); - - $nltr.append( - $('<td>').attr('class', 'center').append( - $('<button>').click(function() - { - var obj = - { - name: $('#new-limit-type :selected').val(), - type: $('#new-limit-hs :selected').val(), - val: $('#new-limit-val').val() - }; - - if( $('#new-limit-appliesto').val() == 'server') - { - settings.settings.config.limits.push(obj); - }else{ - settings.settings.streams[ $('#new-limit-appliesto').val() ].limits.push(obj); - } - - loadSettings(function() - { - showTab('limits'); - }); - - }).text('add new') - ) - ); - $tbody.append($nltr); - + $table.append($tbody); - $('#page').append($table); + $('#page').append($table); + + //build buttons + $('#page').append( + $('<button>').text('Add limit').click(function(){ + $tbody.append(BuildLimitRow({"name":"kb_total", "val":0, "type":"soft"})); + }) + ).append($('<br>')).append( + $('<button>').text('Save all').click(function(){ + //clear current limits + settings.settings.config.limits = Array(); + for (str in settings.settings.streams) { + settings.settings.streams[str].limits = Array(); + } + + //add new limits + $tbody.children('tr').each(function(){ + var newval = null; + switch ($(this).find(".limits_name").val()) { + case 'geo': + var entries = Array(); + $(this).find('.limit_listentry').each(function(){ + var t = $(this).children(':selected').val(); + if (t != ''){ + entries.push(t); + } + }); + if (entries.length > 0) { + newval = $(this).find('.limit_listtype').children(':selected').val() + entries.join(' '); + } + break; + case 'host': + case 'time': + var t = $(this).find('.limit_listentry').val(); + if ((t != undefined) && (t.toString().split(' ').length > 0)) { + newval = $(this).find('.limit_listtype').children(':selected').val() + t; + } + break; + default: + newval = $(this).find(".limits_val").val(); + break; + } + if (newval){ + obj = {"type": $(this).find(".limits_type").val(), "name":$(this).find(".limits_name").val(), "val":newval}; + } + if($(this).find('.new-limit-appliesto').val() == 'server') { + settings.settings.config.limits.push(obj); + }else{ + settings.settings.streams[$(this).find('.new-limit-appliesto').val()].limits.push(obj); + } + }); + loadSettings(function(){ + showTab('limits'); + }); + }) + ); break; diff --git a/lsp/style.css b/lsp/style.css index 0677513d..7801aa0b 100644 --- a/lsp/style.css +++ b/lsp/style.css @@ -64,6 +64,7 @@ table th table td { color: #505050; + vertical-align:top; } @@ -432,4 +433,16 @@ td { margin-top: 25px; margin-bottom: 0px; +} + +#tooltip +{ + position: absolute; + border: 1px solid black; + display: none; + padding: 2px; + background-color: #fee; + opacity: 0.8; + color: black; + font: normal normal 11pt Arial, sans-serif; } \ No newline at end of file