var result = Proxmox.Utils.IP6_cidr_match.exec(v);
// limits according to JSON Schema see
// pve-common/src/PVE/JSONSchema.pm
- return (result !== null && result[1] >= 8 && result[1] <= 120);
+ return (result !== null && result[1] >= 8 && result[1] <= 128);
},
- IP6CIDRAddressText: gettext('Example') + ': 2001:DB8::42/64' + "<br>" + gettext('Valid CIDR Range') + ': 8-120',
+ IP6CIDRAddressText: gettext('Example') + ': 2001:DB8::42/64' + "<br>" + gettext('Valid CIDR Range') + ': 8-128',
IP6CIDRAddressMask: /[A-Fa-f0-9:\/]/,
IP6PrefixLength: function(v) {
IP64AddressText: gettext('Example') + ': 192.168.1.1 2001:DB8::42',
IP64AddressMask: /[A-Fa-f0-9\.:]/,
+ IP64CIDRAddress: function(v) {
+ var result = Proxmox.Utils.IP64_cidr_match.exec(v);
+ if (result === null) {
+ return false;
+ }
+ if (result[1] !== undefined) {
+ return result[1] >= 8 && result[1] <= 128;
+ } else if (result[2] !== undefined) {
+ return result[2] >= 8 && result[2] <= 32;
+ } else {
+ return false;
+ }
+ },
+ IP64CIDRAddressText: gettext('Example') + ': 192.168.1.1/24 2001:DB8::42/64',
+ IP64CIDRAddressMask: /[A-Fa-f0-9\.:\/]/,
+
MacAddress: function(v) {
return (/^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$/).test(v);
},
MacAddressMask: /[a-fA-F0-9:]/,
MacAddressText: gettext('Example') + ': 01:23:45:67:89:ab',
+ MacPrefix: function(v) {
+ return (/^[a-f0-9][02468ace](?::[a-f0-9]{2}){0,2}:?$/i).test(v);
+ },
+ MacPrefixMask: /[a-fA-F0-9:]/,
+ MacPrefixText: gettext('Example') + ': 02:8f - ' + gettext('only unicast addresses are allowed'),
+
BridgeName: function(v) {
return (/^vmbr\d{1,4}$/).test(v);
},
gettext("Maximum characters") + ": 21" + "<br />" +
gettext("Must start with") + ": 'a-z'",
- QemuStartDate: function(v) {
- return (/^(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)$/).test(v);
- },
- QemuStartDateText: gettext('Format') + ': "now" or "2006-06-17T16:01:21" or "2006-06-17"',
-
StorageId: function(v) {
return (/^[a-z][a-z0-9\-\_\.]*[a-z0-9]$/i).test(v);
},
},
proxmoxMailText: gettext('Example') + ": user@example.com",
+ DnsOrIp: function(v) {
+ if (!Proxmox.Utils.DnsName_match.test(v) &&
+ !Proxmox.Utils.IP64_match.test(v)) {
+ return false;
+ }
+
+ return true;
+ },
+ DnsOrIpText: gettext('Not a valid DNS name or IP address.'),
+
HostList: function(v) {
var list = v.split(/[\ \,\;]+/);
var i;
return true;
},
- HostListText: gettext('Not a valid list of hosts')
+ HostListText: gettext('Not a valid list of hosts'),
+
+ password: function(val, field) {
+ if (field.initialPassField) {
+ var pwd = field.up('form').down(
+ '[name=' + field.initialPassField + ']');
+ return (val == pwd.getValue());
+ }
+ return true;
+ },
+
+ passwordText: gettext('Passwords do not match')
+});
+
+// Firefox 52+ Touchscreen bug
+// see https://www.sencha.com/forum/showthread.php?336762-Examples-don-t-work-in-Firefox-52-touchscreen/page2
+// and https://bugzilla.proxmox.com/show_bug.cgi?id=1223
+Ext.define('EXTJS_23846.Element', {
+ override: 'Ext.dom.Element'
+}, function(Element) {
+ var supports = Ext.supports,
+ proto = Element.prototype,
+ eventMap = proto.eventMap,
+ additiveEvents = proto.additiveEvents;
+
+ if (Ext.os.is.Desktop && supports.TouchEvents && !supports.PointerEvents) {
+ eventMap.touchstart = 'mousedown';
+ eventMap.touchmove = 'mousemove';
+ eventMap.touchend = 'mouseup';
+ eventMap.touchcancel = 'mouseup';
+
+ additiveEvents.mousedown = 'mousedown';
+ additiveEvents.mousemove = 'mousemove';
+ additiveEvents.mouseup = 'mouseup';
+ additiveEvents.touchstart = 'touchstart';
+ additiveEvents.touchmove = 'touchmove';
+ additiveEvents.touchend = 'touchend';
+ additiveEvents.touchcancel = 'touchcancel';
+
+ additiveEvents.pointerdown = 'mousedown';
+ additiveEvents.pointermove = 'mousemove';
+ additiveEvents.pointerup = 'mouseup';
+ additiveEvents.pointercancel = 'mouseup';
+ }
+});
+
+Ext.define('EXTJS_23846.Gesture', {
+ override: 'Ext.event.publisher.Gesture'
+}, function(Gesture) {
+ var me = Gesture.instance;
+
+ if (Ext.supports.TouchEvents && !Ext.isWebKit && Ext.os.is.Desktop) {
+ me.handledDomEvents.push('mousedown', 'mousemove', 'mouseup');
+ me.registerEvents();
+ }
+});
+
+// we always want the number in x.y format and never in, e.g., x,y
+Ext.define('PVE.form.field.Number', {
+ override: 'Ext.form.field.Number',
+ submitLocaleSeparator: false
});
// ExtJs 5-6 has an issue with caching
}
});
+// 'Enter' in Textareas and aria multiline fields should not activate the
+// defaultbutton, fixed in extjs 6.0.2
+Ext.define('PVE.panel.Panel', {
+ override: 'Ext.panel.Panel',
+
+ fireDefaultButton: function(e) {
+ if (e.target.getAttribute('aria-multiline') === 'true' ||
+ e.target.tagName === "TEXTAREA") {
+ return true;
+ }
+ return this.callParent(arguments);
+ }
+});
+
// if the order of the values are not the same in originalValue and value
// extjs will not overwrite value, but marks the field dirty and thus
// the reset button will be enabled (but clicking it changes nothing)
// copied from combobox
var me = this;
me.callParent();
- me.applyEmptyText();
// clear and set when not the same
var value = me.getValue();
}
});
+// when refreshing a grid/tree view, restoring the focus moves the view back to
+// the previously focused item. Save scroll position before refocusing.
+Ext.define(null, {
+ override: 'Ext.view.Table',
+
+ jumpToFocus: false,
+
+ saveFocusState: function() {
+ var me = this,
+ store = me.dataSource,
+ actionableMode = me.actionableMode,
+ navModel = me.getNavigationModel(),
+ focusPosition = actionableMode ? me.actionPosition : navModel.getPosition(true),
+ refocusRow, refocusCol;
+
+ if (focusPosition) {
+ // Separate this from the instance that the nav model is using.
+ focusPosition = focusPosition.clone();
+
+ // Exit actionable mode.
+ // We must inform any Actionables that they must relinquish control.
+ // Tabbability must be reset.
+ if (actionableMode) {
+ me.ownerGrid.setActionableMode(false);
+ }
+
+ // Blur the focused descendant, but do not trigger focusLeave.
+ me.el.dom.focus();
+
+ // Exiting actionable mode navigates to the owning cell, so in either focus mode we must
+ // clear the navigation position
+ navModel.setPosition();
+
+ // The following function will attempt to refocus back in the same mode to the same cell
+ // as it was at before based upon the previous record (if it's still inthe store), or the row index.
+ return function() {
+ // If we still have data, attempt to refocus in the same mode.
+ if (store.getCount()) {
+
+ // Adjust expectations of where we are able to refocus according to what kind of destruction
+ // might have been wrought on this view's DOM during focus save.
+ refocusRow = Math.min(focusPosition.rowIdx, me.all.getCount() - 1);
+ refocusCol = Math.min(focusPosition.colIdx, me.getVisibleColumnManager().getColumns().length - 1);
+ focusPosition = new Ext.grid.CellContext(me).setPosition(
+ store.contains(focusPosition.record) ? focusPosition.record : refocusRow, refocusCol);
+
+ if (actionableMode) {
+ me.ownerGrid.setActionableMode(true, focusPosition);
+ } else {
+ me.cellFocused = true;
+
+ // we sometimes want to scroll back to where we were
+ var x = me.getScrollX();
+ var y = me.getScrollY();
+
+ // Pass "preventNavigation" as true so that that does not cause selection.
+ navModel.setPosition(focusPosition, null, null, null, true);
+
+ if (!me.jumpToFocus) {
+ me.scrollTo(x,y);
+ }
+ }
+ }
+ // No rows - focus associated column header
+ else {
+ focusPosition.column.focus();
+ }
+ };
+ }
+ return Ext.emptyFn;
+ }
+});
+
// should be fixed with ExtJS 6.0.2, see:
// https://www.sencha.com/forum/showthread.php?307244-Bug-with-datefield-in-window-with-scroll
Ext.define('Proxmox.Datepicker', {
hideMode: 'visibility'
});
+// ExtJS 6.0.1 has no setSubmitValue() (although you find it in the docs).
+// Note: this.submitValue is a boolean flag, whereas getSubmitValue() returns
+// data to be submitted.
+Ext.define('Proxmox.form.field.Text', {
+ override: 'Ext.form.field.Text',
+
+ setSubmitValue: function(v) {
+ this.submitValue = v;
+ },
+});
+
+// this should be fixed with ExtJS 6.0.2
+// make mousescrolling work in firefox in the containers overflowhandler
+Ext.define(null, {
+ override: 'Ext.layout.container.boxOverflow.Scroller',
+
+ createWheelListener: function() {
+ var me = this;
+ if (Ext.isFirefox) {
+ me.wheelListener = me.layout.innerCt.on('wheel', me.onMouseWheelFirefox, me, {destroyable: true});
+ } else {
+ me.wheelListener = me.layout.innerCt.on('mousewheel', me.onMouseWheel, me, {destroyable: true});
+ }
+ },
+
+ // special wheel handler for firefox. differs from the default onMouseWheel
+ // handler by using deltaY instead of wheelDeltaY and no normalizing,
+ // because it is already
+ onMouseWheelFirefox: function(e) {
+ e.stopEvent();
+ var delta = e.browserEvent.deltaY || 0;
+ this.scrollBy(delta * this.wheelIncrement, false);
+ }
+
+});
+
// force alert boxes to be rendered with an Error Icon
// since Ext.Msg is an object and not a prototype, we need to override it
// after the framework has been initiated