I use odoo 9 is I noticed that it does not have a control for the input format for example for the email field I can enter any character and it will consider it as an email address. So I wanted to know how I can control the input format for a field for example for the email field the presence of "# and the" are mandatory or for the code field VAT for partners the presence of "/" is mandatory .
template.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="assets_backend" name="stock assets mask ext" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/field_mask/static/src/css/mask.css"/>
<script type="text/javascript" src="/field_mask/static/src/js/widgets.js"></script>
<script type="text/javascript" src="/field_mask/static/src/lib/jquery.inputmask.bundle.js"></script>
</xpath>
</template>
</data>
partner_view.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="res_partner_view_purchase_buttons_TVA_RC" model="ir.ui.view">
<field name="name">num.TVA.RC.res.partner.view.purchase.</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//field[#name='website']" position="after">
<field name="CodeTVA" select="1" placeholder="Code TVA" widget="mask" data-inputmask-mask="9999999/A/A/A/999" />
<field name="RC" select="1" placeholder="Num RC"/>
</xpath>
</field>
</record>
</data>
widgets.js
function openerp_field_mask_widgets(instance) {
instance.web.form.FieldMask = instance.web.form.FieldChar.extend({
template : "FieldMask",
render_value: function() {
var show_value = this.get_value();
var field = this;
if (!field.get("effective_readonly")) {
field.$el.find('input').val(show_value);
var mask = field.node.attrs.mask;
field.$el.find('input').inputmask(mask);
} else {
field.$(".oe_form_char_content").text(show_value);
}
},
get_value: function() {
val = this.get('value');
if (!val) {
return '';
}
return val;
},
});
instance.web.form.widgets.add('mask', 'instance.web.form.FieldMask');
}
openerp.field_mask = function(openerp) {
openerp.field_mask = openerp.field_mask || {};
openerp_field_mask_widgets(openerp);
}
You can make your own widget with inputMask by inheriting FieldChar and you can find usefull mudules at odoowidgets or field_mask
Related
I am facing one issue in react native with nativebase.
<Content>
<List>
<ListItem>
<Left style={{ flex: 0 }}>
<Icon name="user" type="SimpleLineIcons"></Icon>
</Left>
<Body>
<Text> Profile </Text>
</Body>
<Right>
<Switch value={this.state.profile} />
</Right>
</ListItem>
....
</List>
</Content>
When i update state(rerender component) list automatically scroll to top/first :
this.setState({profile: true });
How to prevent autoscroll for better user experience?
Please try this prop inside <Content> component:
<Content enableResetScrollToCoords={false} />
You can try this solution too:
handleScroll(event) {
this.setState({ scrollY: event.nativeEvent.contentOffset.y });
}
render() {
if (this.contentRef) {
if (this.contentRef._scrollview) {
this.contentRef._scrollview.resetScrollToCoords({ x: 0, y: this.state.scrollY });
}
}
return (
<Content
ref={(c) => this.contentRef = c}
onScroll={event => this.handleScroll(event)}
>
);
}
I've worked around this issue just by passing the y offset from the scrollview to the parent using the following. By using this.offsetY, an update to the value won't cause a re-render, but it will be passed to the child component when you need it:
In your parent component:
setScrollOffset = (y) => (this.offsetY = y);
return (
<MyChildComponent
data={yourData}
setScrollOffset={this.setScrollOffset}
yOffset={this.offsetY}>
</MyChildComponent>
);
In your child component:
onScrollEndDrag = ({
nativeEvent: {
targetContentOffset: {y},
},
}) => {
this.props.setScrollOffset(y);
};
...
render() {
return (
<ScrollView
contentOffset={{
x: 0,
y: this.props.yOffset !== undefined ? this.props.yOffset : 0,
}}
contentContainerStyle={styles.scrollViewContent}
onScrollEndDrag={this.onScrollEndDrag}>
...
</ScrollView>
)
}
I should add that if you wish for to reset the yOffset to 0 (start at the top of the ScrollView) then you should reset that somewhere else in your parent component if a specific state change occurs.
I created functional list component and render in drawer. In drawer there text and switch component.
My list component was inside renderer method so whenever i toggle switch render method fire and list autocamatilly go to up.
Now, I put list component out of render method. This resolve my issue.
Thanks all guys for your quick response and suggestion.
Example :
render(){
const drawerContent = ()=>(
<Content>
<List>
<Switch value={this.state.flag) />
</List>
</Content>
)
return(
<Drawer content={drawerContent}>
<Container>
....
</Container>
</Drawer>
)
}
To
drawerContent = ()=>(
<Content>
<List>
<Switch value={this.state.flag) />
</List>
</Content>
)
render(){
return(
<Drawer content={this.drawerContent}>
<Container>
....
</Container>
</Drawer>
)
}
I want to add groups attribute in qweb template like this:
<t t-extend="UserMenu">
<t t-jquery=".dropdown-menu" t-operation="replace">
<ul class="dropdown-menu">
<li>Preferences</li>
<li>My Odoo.com account</li>
<li groups="custom_preference_menu.group_yook_about_menu">About Odoo</li>
<li>Help</li>
<li>Log out</li>
</ul>
</t>
</t>
but it'is not working.
how can i solve this problem?
Well the syntax is right. Are you sure that you selected the right group with module_where_the_group_is_created.group_name?
Here is an incomplete answer. It will hide the Preferences menu item for non-admin users:
xml:
<t t-extend="UserMenu">
<t t-jquery="div.dropdown-menu.dropdown-menu-right" t-operation="replace">
<div class="dropdown-menu dropdown-menu-right" role="menu">
<a role="menuitem" href="#" data-menu="shortcuts" class="dropdown-item d-none d-md-inline-block">Shortcuts</a>
<a role="menuitem" href="#" data-menu="settings" class="dropdown-item" id="preference_menuitem">Preferences</a>
<a role="menuitem" href="#" data-menu="logout" class="dropdown-item">Log out</a>
</div>
</t>
</t>
js:
odoo.define('pos_custom_ui.custom_menuitems', function (require) {
"use strict";
var config = require('web.config');
var UserMenu = require('web.UserMenu');
UserMenu.include({
start: function () {
var self = this;
var session = this.getSession();
if (!session.is_admin){
this.$('#preference_menuitem').hide();
}
this.$el.on('click', '[data-menu]', function (ev) {
ev.preventDefault();
var menu = $(this).data('menu');
self['_onMenu' + menu.charAt(0).toUpperCase() + menu.slice(1)]();
});
return this._super.apply(this, arguments).then(function () {
var $avatar = self.$('.oe_topbar_avatar');
if (!session.uid) {
$avatar.attr('src', $avatar.data('default-src'));
return Promise.resolve();
}
var topbar_name = session.name;
if (config.isDebug()) {
topbar_name = _.str.sprintf("%s (%s)", topbar_name, session.db);
}
self.$('.oe_topbar_name').text(topbar_name);
var avatar_src = session.url('/web/image', {
model:'res.users',
field: 'image_128',
id: session.uid,
});
$avatar.attr('src', avatar_src);
});
},
});
});
Include the js file in web.assets_backend:
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="custom_dashboard" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/pos_custom_ui/static/src/js/custom_menuitems.js"></script>
</xpath>
</template>
</odoo>
en I am inserting three input in SOAP request and when trying to get a response I am getting fault message specifying that cannot be cast to a class.
Here I have attached the SOAP response which I am facing.
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
<faultcode>S:Server</faultcode>
<faultstring>...bssv.J570040.valueobject.InternalOrderVO cannot be cast to ...bssv.JP570040.valueobject.IntermediateShipDet</faultstring>
<detail>
<ns2:exception xmlns:ns2="http://jax-ws.dev.java.net/" class="java.lang.ClassCastException" note="To disable this feature, set com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace system property to false">
<message>bssv.J570040.valueobject.InternalOrderVO cannot be cast to bssv.JP570040.valueobject.IntermediateShipDet</message>
<ns2:stackTrace>
<ns2:frame class="bssv.JP570040.valueobject.showOrderDetVO" file="showOrderDetVO.java" line="123" method="<init>" />
<ns2:frame class="bssv.JP570040.InvokeShippingDet" file="InvokeShippingDet.java" line="82" method="GetShippingOrder" />
<ns2:frame class="bssv.JP570040.InvokeShippingDet" file="InvokeShippingDet.java" line="39" method="GetShippingOrder" />
<ns2:frame class="sun.reflect.NativeMethodAccessorImpl" file="NativeMethodAccessorImpl.java" line="native" method="invoke0" />
<ns2:frame class="sun.reflect.NativeMethodAccessorImpl" file="NativeMethodAccessorImpl.java" line="39" method="invoke" />
<ns2:frame class="sun.reflect.DelegatingMethodAccessorImpl" file="DelegatingMethodAccessorImpl.java" line="25" method="invoke" />
<ns2:frame class="java.lang.reflect.Method" file="Method.java" line="597" method="invoke" />
<ns2:frame class="weblogic.wsee.jaxws.WLSInstanceResolver$WLSInvoker" file="WLSInstanceResolver.java" line="92" method="invoke" />
<ns2:frame class="weblogic.wsee.jaxws.WLSInstanceResolver$WLSInvoker" file="WLSInstanceResolver.java" line="74" method="invoke" />
<ns2:frame class="com.sun.xml.ws.server.InvokerTube$2" file="InvokerTube.java" line="151" method="invoke" />
<ns2:frame class="com.sun.xml.ws.server.sei.EndpointMethodHandlerImpl" file="EndpointMethodHandlerImpl.java" line="268" method="invoke" />
<ns2:frame class="com.sun.xml.ws.server.sei.SEIInvokerTube" file="SEIInvokerTube.java" line="100" method="processRequest" />
<ns2:frame class="com.sun.xml.ws.api.pipe.Fiber" file="Fiber.java" line="866" method="__doRun" />
<ns2:frame class="com.sun.xml.ws.api.pipe.Fiber" file="Fiber.java" line="815" method="_doRun" />
<ns2:frame class="com.sun.xml.ws.api.pipe.Fiber" file="Fiber.java" line="778" method="doRun" />
<ns2:frame class="com.sun.xml.ws.api.pipe.Fiber" file="Fiber.java" line="680" method="runSync" />
<ns2:frame class="com.sun.xml.ws.server.WSEndpointImpl$2" file="WSEndpointImpl.java" line="403" method="process" />
<ns2:frame class="com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit" file="HttpAdapter.java" line="532" method="handle" />
<ns2:frame class="com.sun.xml.ws.transport.http.HttpAdapter" file="HttpAdapter.java" line="253" method="handle" />
<ns2:frame class="com.sun.xml.ws.transport.http.servlet.ServletAdapter" file="ServletAdapter.java" line="140" method="handle" />
<ns2:frame class="weblogic.wsee.jaxws.WLSServletAdapter" file="WLSServletAdapter.java" line="171" method="handle" />
<ns2:frame class="weblogic.wsee.jaxws.HttpServletAdapter$AuthorizedInvoke" file="HttpServletAdapter.java" line="708" method="run" />
<ns2:frame class="weblogic.security.acl.internal.AuthenticatedSubject" file="AuthenticatedSubject.java" line="363" method="doAs" />
<ns2:frame class="weblogic.security.service.SecurityManager" file="SecurityManager.java" line="146" method="runAs" />
<ns2:frame class="weblogic.wsee.util.ServerSecurityHelper" file="ServerSecurityHelper.java" line="103" method="authenticatedInvoke" />
<ns2:frame class="weblogic.wsee.jaxws.HttpServletAdapter$3" file="HttpServletAdapter.java" line="311" method="run" />
<ns2:frame class="weblogic.wsee.jaxws.HttpServletAdapter" file="HttpServletAdapter.java" line="336" method="post" />
<ns2:frame class="weblogic.wsee.jaxws.JAXWSServlet" file="JAXWSServlet.java" line="95" method="doRequest" />
<ns2:frame class="weblogic.servlet.http.AbstractAsyncServlet" file="AbstractAsyncServlet.java" line="99" method="service" />
<ns2:frame class="javax.servlet.http.HttpServlet" file="HttpServlet.java" line="820" method="service" />
<ns2:frame class="weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction" file="StubSecurityHelper.java" line="227" method="run" />
<ns2:frame class="weblogic.servlet.internal.StubSecurityHelper" file="StubSecurityHelper.java" line="125" method="invokeServlet" />
<ns2:frame class="weblogic.servlet.internal.ServletStubImpl" file="ServletStubImpl.java" line="300" method="execute" />
<ns2:frame class="weblogic.servlet.internal.TailFilter" file="TailFilter.java" line="26" method="doFilter" />
<ns2:frame class="weblogic.servlet.internal.FilterChainImpl" file="FilterChainImpl.java" line="56" method="doFilter" />
<ns2:frame class="oracle.security.jps.ee.http.JpsAbsFilter$1" file="JpsAbsFilter.java" line="111" method="run" />
<ns2:frame class="java.security.AccessController" file="AccessController.java" line="native" method="doPrivileged" />
<ns2:frame class="oracle.security.jps.util.JpsSubject" file="JpsSubject.java" line="313" method="doAsPrivileged" />
<ns2:frame class="oracle.security.jps.ee.util.JpsPlatformUtil" file="JpsPlatformUtil.java" line="413" method="runJaasMode" />
<ns2:frame class="oracle.security.jps.ee.http.JpsAbsFilter" file="JpsAbsFilter.java" line="94" method="runJaasMode" />
<ns2:frame class="oracle.security.jps.ee.http.JpsAbsFilter" file="JpsAbsFilter.java" line="161" method="doFilter" />
<ns2:frame class="oracle.security.jps.ee.http.JpsFilter" file="JpsFilter.java" line="71" method="doFilter" />
<ns2:frame class="weblogic.servlet.internal.FilterChainImpl" file="FilterChainImpl.java" line="56" method="doFilter" />
<ns2:frame class="oracle.dms.servlet.DMSServletFilter" file="DMSServletFilter.java" line="136" method="doFilter" />
<ns2:frame class="weblogic.servlet.internal.FilterChainImpl" file="FilterChainImpl.java" line="56" method="doFilter" />
<ns2:frame class="weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction" file="WebAppServletContext.java" line="3715" method="wrapRun" />
<ns2:frame class="weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction" file="WebAppServletContext.java" line="3681" method="run" />
<ns2:frame class="weblogic.security.acl.internal.AuthenticatedSubject" file="AuthenticatedSubject.java" line="321" method="doAs" />
<ns2:frame class="weblogic.security.service.SecurityManager" file="SecurityManager.java" line="120" method="runAs" />
<ns2:frame class="weblogic.servlet.internal.WebAppServletContext" file="WebAppServletContext.java" line="2277" method="securedExecute" />
<ns2:frame class="weblogic.servlet.internal.WebAppServletContext" file="WebAppServletContext.java" line="2183" method="execute" />
<ns2:frame class="weblogic.servlet.internal.ServletRequestImpl" file="ServletRequestImpl.java" line="1454" method="run" />
<ns2:frame class="weblogic.work.ExecuteThread" file="ExecuteThread.java" line="209" method="execute" />
<ns2:frame class="weblogic.work.ExecuteThread" file="ExecuteThread.java" line="178" method="run" />
</ns2:stackTrace>
</ns2:exception>
</detail>
</S:Fault>
Just looking at the error I would assume that, there is an error converting internal data item from Date type to external data item of Calendar data type.
Please find a sample of such conversion in bssv
public Calendar setCalendar(Date date)
{
Calendar cal = Calendar.getInstance();
if (date != null)
{
cal.setTime(date);
}
return cal;
}
I have a List component using Checkbox as ItemRenderer. Now the problem is there is no synch between checkbox and List selection.
When the checkbox is selected/desected, I want to update selectedIndices property of the List and vice versa. The list is allowing multiple selection.
Any sample code for this?
My code is as below:
Assign Itemrenderer in List component:
_list.itemRenderer=new ClassFactory(CheckBoxRenderer);
CheckBoxRenderer.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:CheckBox xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
label="{data.name}"
selected="{data.isSelected}">
</mx:CheckBox>
If I understood your problem correctly, here is my solution and the running example.
I added a data grid to let you see that the data provider is changed after user interaction.
//Application
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;
[Bindable]private var dp:ArrayCollection = new ArrayCollection([
{name: "record01", isSelected: false},
{name: "record02", isSelected: true},
{name: "record03", isSelected: false}]);
protected function onClick(event:MouseEvent):void
{
myDG.dataProvider.dispatchEvent( new CollectionEvent(CollectionEvent.COLLECTION_CHANGE));
}
]]>
</fx:Script>
<s:VGroup x="10" y="10">
<s:List dataProvider="{dp}" itemRenderer="renderers.CheckBoxRenderer" click="onClick(event)"/>
<s:Spacer height="20"/>
<s:DataGrid id="myDG" height="120" dataProvider="{dp}">
<s:columns>
<s:ArrayList>
<s:GridColumn dataField="name" headerText="Name" width="70"/>
<s:GridColumn dataField="isSelected" headerText="IsSelected" width="90"/>
</s:ArrayList>
</s:columns>
</s:DataGrid>
</s:VGroup>
</s:Application>
//Renderer
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true">
<fx:Script>
<![CDATA[
protected function onChangeEvent(event:Event):void
{
data.isSelected = !data.isSelected;
}
]]>
</fx:Script>
<s:CheckBox label="{data.name}" selected="{data.isSelected}" change="onChangeEvent(event)"/>
</s:ItemRenderer>
EDIT
As I mentioned the data grid was added only to show the changes in the data provider.
Here is the code without additional components.
You need to control the data provider through the debuger to see that it is being changed.
The button was added just to invoke the debugger on trace() line.
//Application without the grid
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import renderers.CheckBoxRenderer;
[Bindable]private var dp:ArrayCollection = new ArrayCollection([
{name: "record01", isSelected: false},
{name: "record02", isSelected: true},
{name: "record03", isSelected: false}]);
protected function onBtnClick(event:MouseEvent):void
{
trace();
}
]]>
</fx:Script>
<s:VGroup x="10" y="10">
<s:List dataProvider="{dp}" itemRenderer="renderers.CheckBoxRenderer"/>
<s:Button click="onBtnClick(event)"/>
</s:VGroup>
</s:Application>
EDIT2
If you want to restrict the max number of selected items have a look at this code. It works well by me. This time I inserted the itemRenderer in the List definition.
Here is the working example.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
creationComplete="{reculcSelectedCount()}">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
private var _selectedCount:int = 0;
[Bindable]private var dp:ArrayCollection = new ArrayCollection([
{name: "record01", isSelected: false},
{name: "record02", isSelected: true},
{name: "record03", isSelected: false},
{name: "record04", isSelected: false}]);
[Bindable]public function get selectedCount():int
{
return _selectedCount;
}
public function set selectedCount(value:int):void
{
_selectedCount = value;
}
protected function onClick(event:MouseEvent):void
{
reculcSelectedCount();
}
protected function reculcSelectedCount():void
{
selectedCount = 0;
for each (var item:Object in dp)
{
if (item.isSelected)
selectedCount++;
}
}
]]>
</fx:Script>
<s:VGroup x="10" y="10">
<s:List dataProvider="{dp}" click="onClick(event)">
<s:itemRenderer>
<fx:Component>
<mx:HBox>
<fx:Script>
<![CDATA[
protected function onChangeEvent(event:Event):void
{
data.isSelected = !data.isSelected;
}
]]>
</fx:Script>
<s:CheckBox id="cb" label="{data.name}" selected="{data.isSelected}" enabled="{data.isSelected || (!data.isSelected && (outerDocument.selectedCount < 2))}" change="onChangeEvent(event)"/>
</mx:HBox>
</fx:Component>
</s:itemRenderer>
</s:List>
</s:VGroup>
</s:Application>
To avoid having to hard code the child element names I want to remove, I'd like to make a dynamic process to remove child elements when a matching parent element name is found.
My XML file:
<A>
<B1>
<C>C</C>
<D>D</D>
<E>E</E>
<H>H</H>
<MOD>
<C>C</C>
<D>D</D>
<E>E</E>
<F>F</F>
<G>G</G>
</MOD>
</B1>
<B2>
<C>C</C>
<E>E</E>
<H>H</H>
<MOD>
<C>C</C>
<D>D</D>
<E>E</E>
<F>F</F>
<G>G</G>
</MOD>
</B2>
<B3>
<D>D</D>
<E>E</E>
<H>H</H>
<X>X</X>
<MOD>
<C>C</C>
<D>D</D>
<E>E</E>
<F>F</F>
<G>G</G>
<X>G</X>
</MOD>
</B3>
</A>
Desired output:
My XML file:
<A>
<B1>
<C>C</C>
<D>D</D>
<E>E</E>
<H>H</H>
<MOD>
<F>F</F>
<G>G</G>
</MOD>
</B1>
<B2>
<C>C</C>
<E>E</E>
<H>H</H>
<MOD>
<D>D</D>
<F>F</F>
<G>G</G>
</MOD>
</B2>
<B3>
<D>D</D>
<E>E</E>
<H>H</H>
<X>X</X>
<MOD>
<C>C</C>
<F>F</F>
<G>G</G>
</MOD>
</B3>
</A>
My XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:strip-space elements="*"/>
<!-- copy all nodes -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- Remove child elements but keep parent element with same name -->
<xsl:template match="C[../ancestor::*/C]"/>
<xsl:template match="D[../ancestor::*/D]"/>
<xsl:template match="E[../ancestor::*/E]"/>
</xsl:stylesheet>
I think I can combine the remove element code like this
<xsl:template match="C|D|E[../ancestor::*/C|D|E]"/>
I'm not sure how to start, but I'm thinking the process would have to get the parent node names (C,D,E,H), cycle through the children comparing the parent node name to each child node name. When a match is found, remove the child element. Thanks.
As far as I can tell, this stylesheet does what you need. It produces output matching what you say you need by excluding elements that have a parent with a preceding sibling of the same name.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:strip-space elements="*"/>
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="*">
<xsl:if test="not(parent::*/preceding-sibling::*[name() = name(current())])">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
When this XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match="MOD/*[../../* = self::* or preceding-sibling::* = self::*]"/>
</xsl:stylesheet>
...is applied against the provided XML:
<A>
<B1>
<C>C</C>
<D>D</D>
<E>E</E>
<H>H</H>
<MOD>
<C>C</C>
<D>D</D>
<E>E</E>
<F>F</F>
<G>G</G>
</MOD>
</B1>
<B2>
<C>C</C>
<E>E</E>
<H>H</H>
<MOD>
<C>C</C>
<D>D</D>
<E>E</E>
<F>F</F>
<G>G</G>
</MOD>
</B2>
<B3>
<D>D</D>
<E>E</E>
<H>H</H>
<X>X</X>
<MOD>
<C>C</C>
<D>D</D>
<E>E</E>
<F>F</F>
<G>G</G>
<X>G</X>
</MOD>
</B3>
</A>
...the wanted result is produced:
<A>
<B1>
<C>C</C>
<D>D</D>
<E>E</E>
<H>H</H>
<MOD>
<F>F</F>
<G>G</G>
</MOD>
</B1>
<B2>
<C>C</C>
<E>E</E>
<H>H</H>
<MOD>
<D>D</D>
<F>F</F>
<G>G</G>
</MOD>
</B2>
<B3>
<D>D</D>
<E>E</E>
<H>H</H>
<X>X</X>
<MOD>
<C>C</C>
<F>F</F>
<G>G</G>
</MOD>
</B3>
</A>
Explanation:
The first template is the well-known Identity Template, which copies all nodes and attributes from the source document to the result document.
The second template overrides the first and effectively removes all children of <MOD> that:
have the same name as a previous sibling or
have the same name as a sibling of their <MOD> parent (an "uncle-or-aunt")