diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dfa1f26
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/.idea
+install/
+bi-plugin-*/
+bi-plugin-*.jar
\ No newline at end of file
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..4e77e23
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/.gitkeep b/lib/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.xml b/plugin.xml
new file mode 100644
index 0000000..2026b84
--- /dev/null
+++ b/plugin.xml
@@ -0,0 +1,19 @@
+
+
+ com.finebi.plugin.screen_adaptive
+
+ yes
+ 1.1.19
+ 10.0
+ 2019-03-01
+ fay
+
+
+
+
+
+
+
+
+ com.finebi
+
\ No newline at end of file
diff --git a/src/main/java/com/finebi/plugin/ScreenAdaptive.java b/src/main/java/com/finebi/plugin/ScreenAdaptive.java
new file mode 100644
index 0000000..e8f2f14
--- /dev/null
+++ b/src/main/java/com/finebi/plugin/ScreenAdaptive.java
@@ -0,0 +1,23 @@
+package com.finebi.plugin;
+
+import com.finebi.conf.internalimp.component.ShowComponent;
+import com.fr.decision.fun.impl.AbstractWebResourceProvider;
+import com.fr.intelli.record.Focus;
+import com.fr.intelli.record.Original;
+import com.fr.record.analyzer.EnableMetrics;
+import com.fr.web.struct.Atom;
+
+@EnableMetrics
+public class ScreenAdaptive extends AbstractWebResourceProvider {
+
+ @Override
+ public Atom attach() {
+ return ShowComponent.KEY;
+ }
+
+ @Override
+ @Focus(id = "com.finebi.plugin.ScreenAdaptive", text = "BI插件测试", source = Original.PLUGIN)
+ public Atom client() {
+ return ScreenAdaptiveComponent.KEY;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/finebi/plugin/ScreenAdaptiveComponent.java b/src/main/java/com/finebi/plugin/ScreenAdaptiveComponent.java
new file mode 100644
index 0000000..e2bfda5
--- /dev/null
+++ b/src/main/java/com/finebi/plugin/ScreenAdaptiveComponent.java
@@ -0,0 +1,19 @@
+package com.finebi.plugin;
+
+import com.fr.web.struct.Component;
+import com.fr.web.struct.category.ScriptPath;
+import com.fr.web.struct.category.StylePath;
+
+public class ScreenAdaptiveComponent extends Component {
+
+ public static final ScreenAdaptiveComponent KEY = new ScreenAdaptiveComponent();
+
+ private ScreenAdaptiveComponent() {
+
+ }
+
+ @Override
+ public ScriptPath script() {
+ return ScriptPath.build("com/finebi/plugin/web/plugin.screen_adaptive.js");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/finebi/plugin/ScreenAdaptiveLocaleFinder.java b/src/main/java/com/finebi/plugin/ScreenAdaptiveLocaleFinder.java
new file mode 100644
index 0000000..6d6cf0e
--- /dev/null
+++ b/src/main/java/com/finebi/plugin/ScreenAdaptiveLocaleFinder.java
@@ -0,0 +1,13 @@
+package com.finebi.plugin;
+
+import com.fr.plugin.transform.ExecuteFunctionRecord;
+import com.fr.plugin.transform.FunctionRecorder;
+import com.fr.stable.fun.impl.AbstractLocaleFinder;
+@FunctionRecorder
+public class ScreenAdaptiveLocaleFinder extends AbstractLocaleFinder {
+ @Override
+ @ExecuteFunctionRecord
+ public String find() {
+ return "com/finebi/plugin/web/i18n/plugin";
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/com/finebi/plugin/web/i18n/plugin.properties b/src/main/resources/com/finebi/plugin/web/i18n/plugin.properties
new file mode 100644
index 0000000..f2670e4
--- /dev/null
+++ b/src/main/resources/com/finebi/plugin/web/i18n/plugin.properties
@@ -0,0 +1 @@
+BI-Plugin-Scale_Adaptive=
\ No newline at end of file
diff --git a/src/main/resources/com/finebi/plugin/web/i18n/plugin_en_US.properties b/src/main/resources/com/finebi/plugin/web/i18n/plugin_en_US.properties
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/com/finebi/plugin/web/i18n/plugin_ja_JP.properties b/src/main/resources/com/finebi/plugin/web/i18n/plugin_ja_JP.properties
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/com/finebi/plugin/web/i18n/plugin_ko_KR.properties b/src/main/resources/com/finebi/plugin/web/i18n/plugin_ko_KR.properties
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/com/finebi/plugin/web/i18n/plugin_zh_CN.properties b/src/main/resources/com/finebi/plugin/web/i18n/plugin_zh_CN.properties
new file mode 100644
index 0000000..3e00b9b
--- /dev/null
+++ b/src/main/resources/com/finebi/plugin/web/i18n/plugin_zh_CN.properties
@@ -0,0 +1 @@
+BI-Plugin-Scale_Adaptive=\u7B49\u6BD4\u81EA\u9002\u5E94
\ No newline at end of file
diff --git a/src/main/resources/com/finebi/plugin/web/i18n/plugin_zh_TW.properties b/src/main/resources/com/finebi/plugin/web/i18n/plugin_zh_TW.properties
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/com/finebi/plugin/web/plugin.screen_adaptive.js b/src/main/resources/com/finebi/plugin/web/plugin.screen_adaptive.js
new file mode 100644
index 0000000..92a6ab5
--- /dev/null
+++ b/src/main/resources/com/finebi/plugin/web/plugin.screen_adaptive.js
@@ -0,0 +1,223 @@
+!(function () {
+ var scale = 1, transformY = 0, selected = false;
+ var html = document.getElementsByTagName('html')[0];
+
+ var jQuery = $ || window.jQuery;
+ var injectOffset = jQuery.fn.offset;
+ var injectEventFix = jQuery.event.fix;
+ var injectMouseInBounds = jQuery.fn.__isMouseInBounds__;
+
+ // 修正事件偏移
+ function correctEvent(e) {
+ if (e && !e.corrected) {
+ e.pageX = e.pageX / scale;
+ e.pageY = (e.pageY - transformY) / scale;
+ e.clientX = e.clientX / scale;
+ e.clientY = (e.clientY - transformY) / scale;
+ e.corrected = true;
+ }
+ return e;
+ }
+
+ // 进行缩放
+ function transformScale() {
+ var bounds = getScaleBounds();
+ scale = bounds.scale;
+ document.body.style.width = bounds.width + "px";
+ document.body.style.height = bounds.height + "px";
+ document.body.style.transform = "scale(" + bounds.scale+ ")";
+ document.body.style.transformOrigin = "top left";
+ document.body.style["-ms-transform"] = "scale(" + bounds.scale+ ")";
+ document.body.style["-ms-transform-origin"] = "top left";
+ html.style.overflowY = "auto";
+ html.style.backgroundColor = "#2c3d59";
+
+ if (bounds.height * bounds.scale < html.clientHeight) {
+ transformY = (html.clientHeight - bounds.height * bounds.scale) / 2;
+ document.body.style.top = transformY + "px";
+ html.style.overflowY = "hidden";
+ } else {
+ transformY = 0;
+ }
+
+
+ window.scale = window.devicePixelRatio * scale;
+ }
+
+ // 取消缩放
+ function removeScale() {
+ document.body.style.width = "100%";
+ document.body.style.height = "100%";
+ document.body.style.transform = "";
+ document.body.style.transformOrigin = "";
+ document.body.style["-ms-transform"] = "";
+ document.body.style["-ms-transform-origin"] = "";
+ document.body.style.overflowY = "hidden";
+ document.body.style.top = "0px";
+ html.style.backgroundColor = "#ffffff";
+
+ window.scale = window.devicePixelRatio / scale;
+ scale = 1;
+ }
+
+ // 获取缩放倍数,原模板宽高
+ function getScaleBounds() {
+ var widgts = BI.designConfigure.widgets,
+ layoutRatio = BI.designConfigure.layoutRatio,
+ freeLayoutRatio = BI.designConfigure.freeLayoutRatio,
+ freeWidgets = BI.designConfigure.freeWidgetIds;
+ var left = null, right = null, top = null, bottom = null,
+ freeLeft = null, freeRight = null, freeTop = null, freeBottom = null;
+ BI.each(widgts, function (wId, widget) {
+ var bounds = widget.bounds || {};
+ if (BI.contains(freeWidgets, wId)) {
+ freeLeft = BI.isNull(freeLeft) ? bounds.left : Math.min(freeLeft, bounds.left);
+ freeRight = Math.max(freeRight, bounds.left + bounds.width);
+ freeTop = BI.isNull(freeTop) ? bounds.top : Math.min(freeTop, bounds.top);
+ freeBottom = Math.max(freeBottom, bounds.top + bounds.height);
+ } else {
+ left = BI.isNull(left) ? bounds.left : Math.min(left, bounds.left);
+ right = Math.max(right, bounds.left + bounds.width);
+ top = BI.isNull(top) ? bounds.top : Math.min(top, bounds.top);
+ bottom = Math.max(bottom, bounds.top + bounds.height);
+ }
+ });
+
+ var templateWidth = Math.round((right / (layoutRatio.x || 1)) || (freeRight / (freeLayoutRatio.x || 1)));
+ var templateHeight = Math.round((bottom / (layoutRatio.y || 1)) || (freeBottom / (freeLayoutRatio.y || 1)));
+ var scaleRatio = parseFloat((html.clientWidth / templateWidth).toFixed(1));
+ return {
+ scale: scaleRatio,
+ width: html.clientWidth / scaleRatio,
+ height: templateHeight
+ };
+ }
+
+ // 准备环境,主要是纠正事件偏移
+ function prepareEnv() {
+ // IE的fixed元素不受transform:scale影响
+ if (!BI.isIE()) {
+ jQuery.fn.__isMouseInBounds__ = function (e) {
+ var offset2Body = this.get(0).getBoundingClientRect ? this.get(0).getBoundingClientRect() : this.offset();
+ var width = offset2Body.width || this.outerWidth();
+ var height = offset2Body.height || this.outerHeight();
+ var pageX = e.pageX * scale,
+ pageY = e.pageY * scale + transformY;
+ return !(pageX < Math.floor(offset2Body.left) || pageX > offset2Body.left + width
+ || pageY < Math.floor(offset2Body.top) || pageY > offset2Body.top + height);
+ };
+ jQuery.fn.offset = function( options ) {
+ function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+ }
+
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ var el = elem,
+ offsetLeft = 0,
+ offsetTop = 0;
+
+ do{
+ offsetLeft += el.offsetLeft;
+ offsetTop += el.offsetTop;
+ el = el.offsetParent;
+ } while( el );
+
+ var elm = elem;
+ do{
+ offsetLeft -= elm.scrollLeft || 0;
+ offsetTop -= elm.scrollTop || 0;
+ elm = elm.parentNode;
+ } while( elm );
+ win = getWindow( doc );
+ return {
+ top: offsetTop + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: offsetLeft + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+ };
+ jQuery.event.fix = function ( e ) {
+ return correctEvent(injectEventFix.call(this, e));
+ };
+ }
+
+ window.addEventListener('resize', updateScale);
+ }
+
+ function restoreEnv() {
+ if (!BI.isIE()) {
+ jQuery.fn.__isMouseInBounds__ = injectMouseInBounds;
+ jQuery.fn.offset = injectOffset;
+ jQuery.event.fix = injectEventFix;
+ }
+
+ window.removeEventListener('resize', updateScale);
+ }
+
+ function selectHandler () {
+ selected && prepareEnv();
+ selected ? transformScale() : removeScale();
+ !selected && restoreEnv();
+ }
+
+ function updateScale () {
+ if (html.getBoundingClientRect().width !== document.body.getBoundingClientRect().width) {
+ selectHandler();
+ }
+ }
+
+ var injectCaptureMouseMoves = BI.MouseMoveTracker.prototype.captureMouseMoves;
+ var injectOnMouseMove = BI.MouseMoveTracker.prototype._onMouseMove;
+ // 用jQEvent代替MouseEvent
+ function injectMouseMoveTracker() {
+ BI.MouseMoveTracker.prototype.captureMouseMoves = function (e) {
+ var jQEvent = e.originalEvent ? e : jQuery.event.fix(e);
+ injectCaptureMouseMoves.call(this, correctEvent(jQEvent));
+ };
+ BI.MouseMoveTracker.prototype._onMouseMove = function (e) {
+ var jQEvent = e.originalEvent ? e : jQuery.event.fix(e);
+ injectOnMouseMove.call(this, correctEvent(jQEvent));
+ }
+ }
+ injectMouseMoveTracker();
+
+ BI.config("bi.constant.dashboard.toolbar.left.items", function (config) {
+ return BI.concat(config, [{
+ type: "bi.multi_select_item",
+ text: BI.i18nText("BI-Plugin-Scale_Adaptive"),
+ selected: false,
+ listeners: [{
+ eventName: BI.MultiSelectItem.EVENT_CHANGE,
+ action: function () {
+ selected = this.isSelected();
+ selectHandler();
+ }
+ }]
+ }])
+ });
+}());
\ No newline at end of file
diff --git a/src/main/resources/com/finebi/plugin/web/scripts/entry.js b/src/main/resources/com/finebi/plugin/web/scripts/entry.js
new file mode 100644
index 0000000..92a6ab5
--- /dev/null
+++ b/src/main/resources/com/finebi/plugin/web/scripts/entry.js
@@ -0,0 +1,223 @@
+!(function () {
+ var scale = 1, transformY = 0, selected = false;
+ var html = document.getElementsByTagName('html')[0];
+
+ var jQuery = $ || window.jQuery;
+ var injectOffset = jQuery.fn.offset;
+ var injectEventFix = jQuery.event.fix;
+ var injectMouseInBounds = jQuery.fn.__isMouseInBounds__;
+
+ // 修正事件偏移
+ function correctEvent(e) {
+ if (e && !e.corrected) {
+ e.pageX = e.pageX / scale;
+ e.pageY = (e.pageY - transformY) / scale;
+ e.clientX = e.clientX / scale;
+ e.clientY = (e.clientY - transformY) / scale;
+ e.corrected = true;
+ }
+ return e;
+ }
+
+ // 进行缩放
+ function transformScale() {
+ var bounds = getScaleBounds();
+ scale = bounds.scale;
+ document.body.style.width = bounds.width + "px";
+ document.body.style.height = bounds.height + "px";
+ document.body.style.transform = "scale(" + bounds.scale+ ")";
+ document.body.style.transformOrigin = "top left";
+ document.body.style["-ms-transform"] = "scale(" + bounds.scale+ ")";
+ document.body.style["-ms-transform-origin"] = "top left";
+ html.style.overflowY = "auto";
+ html.style.backgroundColor = "#2c3d59";
+
+ if (bounds.height * bounds.scale < html.clientHeight) {
+ transformY = (html.clientHeight - bounds.height * bounds.scale) / 2;
+ document.body.style.top = transformY + "px";
+ html.style.overflowY = "hidden";
+ } else {
+ transformY = 0;
+ }
+
+
+ window.scale = window.devicePixelRatio * scale;
+ }
+
+ // 取消缩放
+ function removeScale() {
+ document.body.style.width = "100%";
+ document.body.style.height = "100%";
+ document.body.style.transform = "";
+ document.body.style.transformOrigin = "";
+ document.body.style["-ms-transform"] = "";
+ document.body.style["-ms-transform-origin"] = "";
+ document.body.style.overflowY = "hidden";
+ document.body.style.top = "0px";
+ html.style.backgroundColor = "#ffffff";
+
+ window.scale = window.devicePixelRatio / scale;
+ scale = 1;
+ }
+
+ // 获取缩放倍数,原模板宽高
+ function getScaleBounds() {
+ var widgts = BI.designConfigure.widgets,
+ layoutRatio = BI.designConfigure.layoutRatio,
+ freeLayoutRatio = BI.designConfigure.freeLayoutRatio,
+ freeWidgets = BI.designConfigure.freeWidgetIds;
+ var left = null, right = null, top = null, bottom = null,
+ freeLeft = null, freeRight = null, freeTop = null, freeBottom = null;
+ BI.each(widgts, function (wId, widget) {
+ var bounds = widget.bounds || {};
+ if (BI.contains(freeWidgets, wId)) {
+ freeLeft = BI.isNull(freeLeft) ? bounds.left : Math.min(freeLeft, bounds.left);
+ freeRight = Math.max(freeRight, bounds.left + bounds.width);
+ freeTop = BI.isNull(freeTop) ? bounds.top : Math.min(freeTop, bounds.top);
+ freeBottom = Math.max(freeBottom, bounds.top + bounds.height);
+ } else {
+ left = BI.isNull(left) ? bounds.left : Math.min(left, bounds.left);
+ right = Math.max(right, bounds.left + bounds.width);
+ top = BI.isNull(top) ? bounds.top : Math.min(top, bounds.top);
+ bottom = Math.max(bottom, bounds.top + bounds.height);
+ }
+ });
+
+ var templateWidth = Math.round((right / (layoutRatio.x || 1)) || (freeRight / (freeLayoutRatio.x || 1)));
+ var templateHeight = Math.round((bottom / (layoutRatio.y || 1)) || (freeBottom / (freeLayoutRatio.y || 1)));
+ var scaleRatio = parseFloat((html.clientWidth / templateWidth).toFixed(1));
+ return {
+ scale: scaleRatio,
+ width: html.clientWidth / scaleRatio,
+ height: templateHeight
+ };
+ }
+
+ // 准备环境,主要是纠正事件偏移
+ function prepareEnv() {
+ // IE的fixed元素不受transform:scale影响
+ if (!BI.isIE()) {
+ jQuery.fn.__isMouseInBounds__ = function (e) {
+ var offset2Body = this.get(0).getBoundingClientRect ? this.get(0).getBoundingClientRect() : this.offset();
+ var width = offset2Body.width || this.outerWidth();
+ var height = offset2Body.height || this.outerHeight();
+ var pageX = e.pageX * scale,
+ pageY = e.pageY * scale + transformY;
+ return !(pageX < Math.floor(offset2Body.left) || pageX > offset2Body.left + width
+ || pageY < Math.floor(offset2Body.top) || pageY > offset2Body.top + height);
+ };
+ jQuery.fn.offset = function( options ) {
+ function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+ }
+
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ var el = elem,
+ offsetLeft = 0,
+ offsetTop = 0;
+
+ do{
+ offsetLeft += el.offsetLeft;
+ offsetTop += el.offsetTop;
+ el = el.offsetParent;
+ } while( el );
+
+ var elm = elem;
+ do{
+ offsetLeft -= elm.scrollLeft || 0;
+ offsetTop -= elm.scrollTop || 0;
+ elm = elm.parentNode;
+ } while( elm );
+ win = getWindow( doc );
+ return {
+ top: offsetTop + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: offsetLeft + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+ };
+ jQuery.event.fix = function ( e ) {
+ return correctEvent(injectEventFix.call(this, e));
+ };
+ }
+
+ window.addEventListener('resize', updateScale);
+ }
+
+ function restoreEnv() {
+ if (!BI.isIE()) {
+ jQuery.fn.__isMouseInBounds__ = injectMouseInBounds;
+ jQuery.fn.offset = injectOffset;
+ jQuery.event.fix = injectEventFix;
+ }
+
+ window.removeEventListener('resize', updateScale);
+ }
+
+ function selectHandler () {
+ selected && prepareEnv();
+ selected ? transformScale() : removeScale();
+ !selected && restoreEnv();
+ }
+
+ function updateScale () {
+ if (html.getBoundingClientRect().width !== document.body.getBoundingClientRect().width) {
+ selectHandler();
+ }
+ }
+
+ var injectCaptureMouseMoves = BI.MouseMoveTracker.prototype.captureMouseMoves;
+ var injectOnMouseMove = BI.MouseMoveTracker.prototype._onMouseMove;
+ // 用jQEvent代替MouseEvent
+ function injectMouseMoveTracker() {
+ BI.MouseMoveTracker.prototype.captureMouseMoves = function (e) {
+ var jQEvent = e.originalEvent ? e : jQuery.event.fix(e);
+ injectCaptureMouseMoves.call(this, correctEvent(jQEvent));
+ };
+ BI.MouseMoveTracker.prototype._onMouseMove = function (e) {
+ var jQEvent = e.originalEvent ? e : jQuery.event.fix(e);
+ injectOnMouseMove.call(this, correctEvent(jQEvent));
+ }
+ }
+ injectMouseMoveTracker();
+
+ BI.config("bi.constant.dashboard.toolbar.left.items", function (config) {
+ return BI.concat(config, [{
+ type: "bi.multi_select_item",
+ text: BI.i18nText("BI-Plugin-Scale_Adaptive"),
+ selected: false,
+ listeners: [{
+ eventName: BI.MultiSelectItem.EVENT_CHANGE,
+ action: function () {
+ selected = this.isSelected();
+ selectHandler();
+ }
+ }]
+ }])
+ });
+}());
\ No newline at end of file