Created
December 11, 2014 14:37
-
-
Save logical-and/521ccdd0958d031ba153 to your computer and use it in GitHub Desktop.
Sermik code examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'jsclass/class', | |
'./WidgetService', | |
'app/common/layout/manager', | |
'app/common/layout/model', | |
'app/common/datatable/component.datatable', | |
'Shared/Base/ConfigureGrid', | |
'Shared/Filter/filter', | |
'Shared/Filter/PageFilterSortInfo', | |
'Shared/Base/LoadMask', | |
'Shared/Extensions/ScopedWorkspace', | |
'Shared/Util/Widget/GenericHelpers', | |
'./WidgetLoader', | |
'./Util', | |
'nunjucks', | |
'Shared/Extensions/WindowTitleForDate', | |
'async' | |
], function ( | |
Class, WidgetService, Manager, Model, Datatable, ConfigureGrid, Filter, PageFilterSortInfo, | |
LoadMask, ScopedWorkspace, GenericHelpers, WidgetLoader, Util, nunjucks, WindowTitleForDate, | |
Async | |
) { | |
'use strict'; | |
var DIR = 'Shared/WidgetFoundation/', | |
$CacheMemory = {}; | |
return new Class( | |
{ | |
extend: { | |
EXPORT_TYPE: { | |
DETACH: 'DETACH' | |
}, | |
loader: function(settings) { | |
return new WidgetLoader(this, settings); | |
} | |
}, | |
settings: { | |
// default: { features: {} } - workspace and subworkspace, all tabs, main and detach | |
// | |
// workspace: { default: { default: { features: {} } } } - workspace, all tabs, main and detach | |
// workspace: { default: { main: { features: {} } } } - workspace, all tabs, main | |
// workspace: { reports: { default: { features: {} } } } - workspace, reports tab, main and detach | |
// workspace: { reports: { main: { features: {} } } } - workspace, reports tab, main | |
// workspace: { reports: { detach: { features: {} } } } - workspace, reports tab, detach | |
// | |
// subworkspace: { default: { features: {} } } - subworkspace, main and detach | |
// subworkspace: { main: { features: {} } } - subworkspace, main | |
// subworkspace: { detach: { features: {} } } - subworkspace, detach | |
default: { | |
title: 'Abstract Widget Title', | |
features: { | |
export: true, | |
exportType: ['DETACH'], | |
maximize: true, | |
mininize: true, | |
close: true, | |
resize: true, | |
drag: true | |
}, | |
size: { | |
width: 500, | |
height: 400 | |
}, | |
listeners: { | |
// format: eventName: function() {}, or eventName: [function() {}] | |
// widgetInitialized: [], | |
// widgetPassive: function() { console.info('just become passive'); } | |
// available event types: | |
// eventName - widget foundation event (see this.eventsMap) | |
// widget:eventName (see this.frameworkEventsMap) | |
// service:serviceName | |
}, | |
// Methods, which will be passed to this[methodKey] | |
methods: {}, | |
plugins: { | |
// PluginPath: { parameters: 'here' } | |
}, | |
internal: { | |
workspaceChangeWorkaroundTimeout: 50, | |
paths: { | |
service: 'Service', | |
view: ':text:' + DIR + 'View/AbstractWidget.html' // :text:, :require:, :service: or direct url (without html) | |
}, | |
services: { | |
getState: 'AUM/GetWidgetState', | |
saveState: 'AUM/SetWidgetState', | |
getStateNoId: 'User/GetWidgetStateWithoutId', | |
saveStateNoId: 'User/SetWidgetStateWithoutId' | |
} | |
} | |
} | |
}, | |
// Fetched settings | |
actualSettings: {}, | |
// State | |
originalState: {}, | |
state: {}, | |
service: null, | |
eventListeners: null, | |
memory: null, | |
plugins: null, | |
// Widget | |
initialized: false, | |
id: null, // unique id | |
widgetFrameworkPath: null, // framework internal, ie AssetsUnderManagement/AssetsUnderManagement:Assets Under Management | |
widgetPath: null, // ie AssetsUnderManagement/AssetsUnderManagement | |
widgetWorkspaceTab: null, | |
widgetObject: null, | |
widgetBodyContainerId: null, | |
isWidgetDetached: null, | |
widgetArgs: [], | |
workspaceContext: null, | |
spinner: null, | |
// Mapping | |
featuresMap: {}, | |
// WidgetFoundation events | |
eventsMap: { | |
settingsFetched: 'settingsFetched', | |
widgetInitialized: 'widgetInitialized', | |
viewInitialized: 'viewInitialized', | |
stateLoaded: 'stateLoaded', | |
statePersisting: 'statePersisting', | |
exportDataToDetached: 'exportDataToDetached', | |
detachedReceiveData: 'detachedReceiveData' | |
}, | |
// Framework events | |
frameworkEventsMap: { | |
// Features | |
onExportClicked: Model.WIDGET_EXPORT, | |
onSettingsClicked: 'settings', | |
onVisualizationClicked: Model.WIDGET_VISUALIZATION, | |
onFilterClicked: 'filter', | |
onRefreshClicked: 'refresh', | |
onResized: Model.AFTER_RESIZE, | |
onMaximized: Model.AFTER_MAXIMIZE, | |
onCascaded: Model.AFTER_CASCADE, | |
onDragged: Model.WIDGET_DRAG_COMPLETED, | |
onClose: Model.WIDGET_CLOSE, | |
// Detach | |
onDetachedInitializing: Model.EXPORTED_VIEW_READY, | |
onDetachedDataReceived: Model.EXPORTED_VIEW_DATA_EVENT, | |
// Strange one-instance widget strategy events | |
onWidgetPassivate: Model.VIEW_IN_PASSIVE_MODE, | |
onWidgetActivate: Model.VIEW_IN_ACTIVE_MODE, | |
onScopeChanged: ScopedWorkspace.SCOPE_CHANGE_EVENT, | |
onUserPreferenceChanged: 'USER_PREFERENCES_SAVED' | |
}, | |
// Work like localization for export items | |
exportTypesMap: { | |
DETACH: 'Detach' | |
}, | |
workspacesIdMap: { | |
"Home": 1, | |
"Clients": 2, | |
"Worklist": 3, | |
"Markets": 4, | |
"Resources": 5, | |
"Trading": 6, | |
"Services": 8, | |
"Reports": 9, | |
"Fixed Income": 10, | |
"Back Office": 19, | |
"Admin": 20, | |
// "Home": 21, | |
// "Home": 22, | |
"Accounts": 23, | |
"Documents": 24, | |
// "Markets": 25, | |
"Bill Pay": 26, | |
"Credit Card Activity": 27 | |
// "Trading": 28, | |
}, | |
initialize: function (settings, whom, isDetached, args, widgetModulePath) { | |
var self = this; | |
// Merge inherited values in the right way | |
Util.forEach(['settings', 'featuresMap', 'eventsMap', 'exportTypesMap', 'frameworkEventsMap'], function(i, key) { | |
var merged = {}; | |
Util.forEach(self.__eigen__().lookup(key), function(i, value) { | |
merged = Util.Object.merge(merged, value); | |
}); | |
self[key] = merged; | |
}); | |
// Merge settings | |
this.settings = Util.Object.merge(this.settings, settings); | |
this.widgetFrameworkPath = widgetModulePath; | |
this.widgetPath = widgetModulePath.split(':')[0]; | |
this.isWidgetDetached = !!isDetached; | |
this.widgetArgs = args || []; | |
(function (initSettings, nextStep) { | |
// Define some settings manually | |
if (!self.isWidgetDetached) { | |
self.updateWorkspaceContext(); | |
setTimeout(function() { | |
// don't work for clients tab | |
// self.widgetWorkspaceTab = Manager.getWorkspaces()[Manager.getWorkspace()].name; | |
self.widgetWorkspaceTab = $('#workspaceTabsHolder').find('.workspace.active').text(); | |
initSettings(nextStep); | |
}, self.settings.default.internal.workspaceChangeWorkaroundTimeout); | |
} | |
// Receive settings from original widget | |
else { | |
var dummyWindow = new Model.WindowProperties(whom, self.widgetFrameworkPath); | |
var dummyWidget = Manager.createWidget(dummyWindow); | |
Manager.renderWidget(dummyWidget, function(event, postMessage) { | |
if (self.frameworkEventsMap.onDetachedDataReceived == event) { | |
if (postMessage.state) { | |
self.originalState = Util.Object.clone(postMessage.state); | |
self.state = Util.Object.clone(postMessage.state); | |
} | |
self.widgetWorkspaceTab = postMessage.widgetWorkspaceTab || 'Unknown'; | |
self.workspaceContext = postMessage.workspaceContext || {}; | |
(function(next) { | |
if (!self.initialized) initSettings(next); | |
else next(); | |
})(function() { | |
nextStep(function() { | |
self.fireEvent(self.eventsMap.detachedReceiveData, { | |
postMessage: postMessage | |
}); | |
if (postMessage.state) { | |
self.fireEvent(self.eventsMap.stateLoaded, postMessage.state); | |
} | |
}); | |
}); | |
} | |
}, ''); | |
// Prepare html to make it wonderful | |
$('#' + dummyWidget.getId()).hide(); | |
$('body #centerpane').prepend($('<div id="loading" style="text-align: center;height: 100%;display: table;width: 100%;">' + | |
'<span style="display: table-cell;vertical-align: middle;font-size: 150%;" class="color-white">' + | |
'Exporting...' + | |
'</span>' + | |
'</div>') | |
); | |
Manager.subscribeToEvent(self.frameworkEventsMap.onDetachedDataReceived, self.widgetFrameworkPath); | |
Manager.sendToParentWindow(self.widgetFrameworkPath, self.frameworkEventsMap.onDetachedInitializing); | |
} | |
})(function(callback) { | |
// Fetch settings from given hash | |
self.actualSettings = self._fetchActualSettings(self.settings); | |
// Store methods to use it as native | |
Util.forEach(self.actualSettings.methods, function(methodKey, method) { | |
if (self[methodKey]) throw new Error('Cannot override "' + methodKey + '"! Method must have unique name!'); | |
self[methodKey] = method.bind(self); | |
}); | |
self.fireEvent(self.eventsMap.settingsFetched); | |
// Initialize plugins | |
if (!Util.Object.isEmpty(self.actualSettings.plugins)) { | |
self.plugins = []; | |
Async.each(Util.Object.getKeys(self.actualSettings.plugins), function(plugin, cb) { | |
require([plugin], function(Plugin) { | |
self.plugins[plugin] = new Plugin(self, self.actualSettings.plugins[plugin], cb); | |
}); | |
}, callback); | |
} | |
else callback(); | |
}, function (listenersInitialized) { | |
// Go next | |
var windowProperties = new Model.WindowProperties(whom, self.widgetFrameworkPath); | |
// Title | |
if (self.isWorkspace()) windowProperties.setTitle(self.actualSettings.title); | |
else windowProperties.setTitle(self.actualSettings.title + ' for ' + self.workspaceContext.display); | |
// Features | |
var features = []; | |
for (var feature in self.featuresMap) { | |
if (self.featuresMap.hasOwnProperty(feature)) { | |
if (self.actualSettings.features[feature]) features.push(self.featuresMap[feature]); | |
} | |
} | |
if (features.length) windowProperties.showDefaultMenuOptions(features); | |
windowProperties.showDetachOption(self.actualSettings.features.export); | |
// If not detached, then we customize some window properties | |
if (!self.isWidgetDetached) { | |
windowProperties.isMaximizable(self.actualSettings.features.maximize); | |
windowProperties.isMinimizable(self.actualSettings.features.minimize); | |
windowProperties.isClosable(self.actualSettings.features.close); | |
windowProperties.isResizable(self.actualSettings.features.resize); | |
windowProperties.isDraggable(self.actualSettings.features.drag); | |
} | |
// Size | |
if (!self.isWidgetDetached) { | |
windowProperties.setWidth(self.actualSettings.size.width); | |
windowProperties.setHeight(self.actualSettings.size.height); | |
windowProperties.setMinSize(self.actualSettings.size.width, self.actualSettings.size.height); | |
} | |
else { | |
var viewPortDims = viewport(); | |
windowProperties.setWidth(viewPortDims.width); | |
windowProperties.setHeight(viewPortDims.height); | |
} | |
self.widgetObject = Manager.createWidget(windowProperties); | |
// And here we go | |
self.stackInitServices(function() { | |
self.stackInitEventListeners(function() { | |
listenersInitialized && listenersInitialized(); | |
self.stackInitView(function() { | |
if (self.isWidgetDetached) self.getNode().hide(); | |
// Subworkspace title | |
if (self.isSubworkspace()) { | |
self.appendToTitle('for ' + self.workspaceContext.display); | |
} | |
self.showSpinner(); | |
if (self.isWidgetDetached) { | |
$('#loading').remove(); | |
self.getNode().show(); | |
} | |
self.stackInitState(function() { | |
self.hideSpinner(); | |
self.initialized = true; | |
self.fireEvent(self.eventsMap.widgetInitialized); | |
}); | |
}); | |
}); | |
}); | |
}); | |
}, | |
/** | |
* Fetch settings for current workspace/subworkspace from all settings (smart merge) | |
* | |
* @param allSettings | |
* @returns {{}} | |
* @private | |
*/ | |
_fetchActualSettings: function(allSettings) { | |
var settings = Util.Object.clone(allSettings), | |
paths = ['default']; | |
if (this.isWorkspace()) { | |
// Defaults | |
paths.push('workspace.default.default'); | |
// With tab | |
var currentTab = this.getCurrentTabName().toLowerCase(); | |
paths.push('workspace.' + currentTab + '.default'); | |
// With widget state (main or detach) | |
paths.push('workspace.default.' + (!this.isDetached() ? 'main' : 'detach')); | |
paths.push('workspace.' + currentTab + '.' + (!this.isDetached() ? 'main' : 'detach')); | |
} | |
else { | |
// Defaults | |
paths.push('subworkspace.default'); | |
// With widget state (main or detach) | |
paths.push('subworkspace.' + (!this.isDetached() ? 'main' : 'detach')); | |
} | |
var fetchedSettings = {}; | |
for (var i = 0; i < paths.length; i++) { | |
fetchedSettings = Util.Object.merge(fetchedSettings, Util.Object.getPath(settings, paths[i], {})); | |
} | |
return fetchedSettings; | |
}, | |
// --- Stack | |
/** | |
* Initialize widget services | |
* @private | |
*/ | |
stackInitServices: function(next) { | |
var self = this; | |
require([this._determineServicesPath()], function (Service) { | |
self.service = (new Service).initializeServices(self.getWidgetPath()); | |
// Listen services as events | |
Util.forEach(self.service.servicesConfig, function(serviceName) { | |
self.service.listenService(serviceName, function(data) { | |
if (!self.active) return; | |
self.fireEvent('service:' + serviceName, data); | |
}); | |
}); | |
next(); | |
}); | |
}, | |
/** | |
* Subscribe to events | |
* @private | |
*/ | |
stackInitEventListeners: function(next) { | |
var self = this; | |
Util.forEach(this.actualSettings.listeners, function(eventName) { | |
var events = self.actualSettings.listeners[eventName]; | |
if ('function' == typeof events) events = [events]; | |
for (var i = 0; i < events.length; i++) { | |
self.listenEvent(eventName, events[i]); | |
} | |
}); | |
next(); | |
}, | |
stackInitState: function(next) { | |
if (!this.isWidgetDetached) this.loadState(next); | |
else next(); | |
}, | |
// --- Generic | |
getNodeId: function () { | |
return this.widgetObject.getId(); | |
}, | |
getNode: function () { | |
return $('#' + this.getNodeId()); | |
}, | |
getWidgetObject: function() { | |
return this.widgetObject; | |
}, | |
getNodeBodyContainerId: function() { | |
return this.widgetBodyContainerId; | |
}, | |
getNodeBodyContainer: function() { | |
return $('#' + this.widgetBodyContainerId); | |
}, | |
getWidgetFrameworkPath: function() { | |
return this.widgetFrameworkPath; | |
}, | |
getWidgetPath: function () { | |
return this.widgetPath; | |
}, | |
/** | |
* For require.js usage | |
* @param {Boolean} [trailingSlash=true] | |
* @returns {String} | |
*/ | |
getWidgetDir: function(trailingSlash) { | |
if (undefined === trailingSlash) trailingSlash = true; | |
return this.widgetPath.replace(/\/[^/]+$/, '') + (trailingSlash ? '/' : ''); | |
}, | |
getSettings: function () { | |
return this.actualSettings; | |
}, | |
getAllSettings: function() { | |
return this.settings; | |
}, | |
isInitialized: function() { | |
return this.initialized; | |
}, | |
// --- Environment | |
isDetached: function() { | |
return this.isWidgetDetached; | |
}, | |
getArgs: function() { | |
return this.widgetArgs; | |
}, | |
getWorkspaceContext: function() { | |
return this.workspaceContext; | |
}, | |
updateWorkspaceContext: function() { | |
if (this.isWidgetDetached) throw new Error('Cannot update workspace context for detached widget'); | |
this.workspaceContext = ScopedWorkspace.getScopeOfCurrentWorkspace(); | |
return this; | |
}, | |
isWorkspace: function() { | |
return this.workspaceContext === ScopedWorkspace.SCOPE_UNDEFINED | |
}, | |
isSubworkspace: function() { | |
return !this.isWorkspace(); | |
}, | |
getCurrentTabName: function() { | |
return this.widgetWorkspaceTab; | |
}, | |
// --- Events | |
listenEvent: function (event, handler) { | |
if (!this.eventListeners) this.eventListeners = {}; | |
var self = this; | |
var eventModificators = { | |
once: function(event, handler) { | |
var extraHandler = function() { | |
// Remove event | |
if (~self.eventListeners[event].indexOf(extraHandler)) { | |
delete self.eventListeners[event][self.eventListeners[event].indexOf(extraHandler)]; | |
} | |
// Call original handler | |
handler.apply(this, arguments); | |
}; | |
return extraHandler; | |
} | |
}; | |
var extraEventMatch = event.match(/:([^:]+)$/); | |
if (extraEventMatch && eventModificators[extraEventMatch[1]]) { | |
// if (!eventModificators[extraEventMatch[1]]) throw new Error('Modificator ' + extraEventMatch[1] + ' is unknown'); | |
// Remove modificator from event | |
event = event.replace(/:([^:]+)$/, ''); | |
handler = eventModificators[extraEventMatch[1]](event, handler); | |
} | |
if (!this.eventListeners[event]) this.eventListeners[event] = []; | |
this.eventListeners[event].push(handler); | |
return this; | |
}, | |
fireEvent: function(event, args) { | |
if (!this.eventListeners) this.eventListeners = {}; | |
// Currently used for widget final instance handlers (settings.listeners) | |
if (this.eventListeners[event]) { | |
for (var i = 0; i < this.eventListeners[event].length; i++) { | |
this.eventListeners[event][i].call(this, args); | |
} | |
} | |
// Internal event methods | |
var methodEventHandler = event.replace(/^[^:]+:/, '') + 'EventHandler'; | |
if (this[methodEventHandler] && 'function' == typeof this[methodEventHandler]) this[methodEventHandler].call(this, args); | |
return this; | |
}, | |
// --- Event handlers | |
onCloseEventHandler: function() { | |
this.saveStateIfChanged(); | |
}, | |
onExportClickedEventHandler: function() { | |
var self = this; | |
require(["Shared/Extensions/Export"], function (_export) { | |
var items = []; | |
Util.forEach(self.actualSettings.features.exportType, function(i, type) { | |
if (self.exportTypesMap[type]) { | |
items.push({ | |
name: self.exportTypesMap[type], | |
callback: self.onExportingEventHandler.bind(self), | |
id: Util.getUniqueId(), | |
type: type | |
}); | |
} | |
}); | |
_export.createExportmenu(self.getNodeId(), self.getNodeBodyContainerId(), items); | |
}); | |
}, | |
onExportingEventHandler: function(item) { | |
var self = this; | |
switch (item.type) { | |
case 'DETACH': | |
Manager.detachWindow(this.widgetFrameworkPath, function(event) { | |
// Export general values | |
if (self.frameworkEventsMap.onDetachedInitializing == event) { | |
var postMessage = { | |
state: self.state, | |
widgetWorkspaceTab: self.widgetWorkspaceTab, | |
workspaceContext: self.workspaceContext | |
}; | |
self.fireEvent(self.eventsMap.exportDataToDetached, { | |
postMessage: postMessage, | |
sendMethod: this.sendMessage.bind(this) | |
}); | |
this.sendMessage(postMessage); | |
} | |
// console.info('export layoutEventHandler: ', arguments, this); | |
}); | |
break; | |
default: | |
console.error('Unknown export type: ' + item.type); | |
} | |
}, | |
onScopeChangedEventHandler: function() { | |
this.updateWorkspaceContext().appendToTitle('for ' + this.workspaceContext.display); | |
}, | |
// --- Services | |
getService: function() { | |
return this.service; | |
}, | |
getServices: function() { | |
return WidgetService; | |
}, | |
callOwnService: function(service, parameters, callback) { | |
this.service.call(this.service.getRealServiceName(service), parameters, callback); | |
return this; | |
}, | |
_determineServicesPath: function () { | |
return this.getWidgetDir() + this.actualSettings.internal.paths.service; | |
}, | |
// --- State | |
getFromState: function (path, def) { | |
return Util.Object.getPath(this.state, path, def); | |
}, | |
setToState: function (path, value) { | |
Util.Object.setPath(this.state, path, value); | |
return this; | |
}, | |
loadState: function (callback) { | |
var requestCallback = function (data) { | |
var state = data || {}; | |
this.state = state; | |
this.originalState = Util.Object.clone(state); | |
this.fireEvent(this.eventsMap.stateLoaded, state); | |
callback(state); | |
}.bind(this); | |
if (this.actualSettings.stateId) { | |
console.warn('stateId is deprecated, but used in "' + this.widgetPath + '" - ' + this.actualSettings.stateId); | |
WidgetService.directRequest(this.actualSettings.internal.services.getState, | |
{ id: this.actualSettings.stateId }, 'GET', 'json', function(data) { | |
requestCallback(data && data.Preference ? data.Preference : {}); | |
}); | |
} | |
else { | |
WidgetService.directRequest(this.actualSettings.internal.services.getStateNoId, | |
{ | |
widgetPath: this.widgetFrameworkPath, | |
workspaceId: Util.Object.getPath(this.workspacesIdMap, this.getCurrentTabName(), this.workspacesIdMap.Home), | |
isSubworkspace: this.isSubworkspace() | |
}, 'GET', 'json', function(data) { | |
if (data && data.json) data = data.json; | |
requestCallback(data); | |
}, true); | |
} | |
return this; | |
}, | |
isStateChanged: function () { | |
// skip whitespace from comparison | |
return JSON.stringify(this.originalState).replace(/\s+/g, '') != JSON.stringify(this.state).replace(/\s+/g, ''); | |
}, | |
saveState: function (callback) { | |
var self = this; | |
this.fireEvent(this.eventsMap.statePersisting, this.state); | |
var requestCallback = function () { | |
self.originalState = Util.Object.clone(self.state); | |
if (callback) callback(); | |
}.bind(this); | |
if (this.actualSettings.stateId) { | |
console.warn('stateId is deprecated, but used in "' + this.widgetPath + '" - ' + this.actualSettings.stateId); | |
WidgetService.directRequest(this.actualSettings.internal.services.saveState, | |
{ id: this.actualSettings.stateId, Preference: this.state }, 'POST', 'json', requestCallback); | |
} | |
else { | |
WidgetService.directRequest(this.actualSettings.internal.services.saveStateNoId, | |
{ | |
widgetPath: this.widgetFrameworkPath, | |
workspaceId: Util.Object.getPath(this.workspacesIdMap, this.getCurrentTabName(), this.workspacesIdMap.Home), | |
isSubworkspace: this.isSubworkspace(), | |
json: this.state | |
}, 'POST', 'json', function(data) { | |
if (!data.Response) alert('Error: state wasn`t persisted! { Response: false }'); | |
requestCallback(); | |
}); | |
} | |
return this; | |
}, | |
saveStateIfChanged: function(callback) { | |
if (!this.isStateChanged()) { if (callback) callback(); } | |
else this.saveState(callback); | |
return this; | |
}, | |
// --- View | |
loadView: function (callback) { | |
this.loadHTML(this.actualSettings.internal.paths.view, callback); | |
return this; | |
}, | |
loadHTML: function(loadUrl, callback) { | |
loadUrl = loadUrl.replace(/{WidgetFoundation}\/?/, DIR); | |
// Service loading | |
if (-1 != loadUrl.indexOf(':service:')) { | |
WidgetService.call(loadUrl.replace(':service:'), callback); | |
} | |
// Require | |
else if (-1 != loadUrl.indexOf(':require:')) { | |
require([loadUrl.replace(':require:')], callback); | |
} | |
// Require-text | |
else if (-1 != loadUrl.indexOf(':require-text:')) { | |
require(['Lib/Vendor/RequireJS/text!' + loadUrl.replace(':require-text:', '')], callback); | |
} | |
// Text | |
else if (-1 != loadUrl.indexOf(':text:')) { | |
nunjucks.render(loadUrl.replace(':text:', '') | |
// Relative to widget path | |
.replace(new RegExp('^\./'), this.widgetPath.replace(/[^/]+$/, '') + '/'), | |
function (err, html) { | |
if (err) { | |
console.error(err); | |
} | |
else setTimeout(function() { callback(html); }, 0); | |
}); | |
} | |
// URL request | |
else { | |
WidgetService.directRequest(loadUrl, {}, 'GET', 'html', function (template) { | |
callback(template); | |
}.bind(this)); | |
} | |
return this; | |
}, | |
// --- Spinner | |
getSpinner: function() { | |
if (!this.spinner) { | |
if (this.widgetBodyContainerId) { | |
this.spinner = new LoadMask.LoadMask(this.getNodeBodyContainer().parent().prop('id')); | |
} | |
else { | |
console.warn('Cannot construct spinner for ' + this.widgetPath + '! Node id is unknown yet!'); | |
} | |
} | |
return this.spinner; | |
}, | |
showSpinner: function() { | |
if (!this.spinnerCallCount) this.spinnerCallCount = 0; | |
// Count how much it called to show | |
this.spinnerCallCount++; | |
if (1 == this.spinnerCallCount) { | |
var spinner = this.getSpinner(); | |
if (spinner) spinner.start(); | |
} | |
return this; | |
}, | |
hideSpinner: function() { | |
if (!this.spinnerCallCount) this.spinnerCallCount = 0; | |
// Prevent from going under zero number | |
if (this.spinnerCallCount > 0) this.spinnerCallCount--; | |
if (0 == this.spinnerCallCount) { | |
var spinner = this.getSpinner(); | |
if (spinner) spinner.stop(); | |
} | |
return this; | |
}, | |
// --- Memory cache | |
getFromGlobalCacheOrExecute: function(handler, key, callback) { | |
if ('function' == typeof key) { | |
callback = key; | |
key = undefined; | |
} | |
if (undefined === key) key = Util.md5(handler.toString()); | |
(function(handle) { | |
// Already cached | |
if ($CacheMemory[key]) handle($CacheMemory[key]); | |
// Need to be cached | |
else handler(function(result) { callback($CacheMemory[key] = result); }); | |
})(callback); | |
}, | |
getFromMemory: function(path, def) { | |
if (!this.memory) this.memory = {}; | |
return Util.Object.getPath(this.memory, path, def); | |
}, | |
setToMemory: function(path, value) { | |
if (!this.memory) this.memory = {}; | |
Util.Object.setPath(this.memory, path, value); | |
return this; | |
}, | |
// --- Title & header | |
/** | |
* Set widget title | |
* @param {String} title | |
*/ | |
setTitle: function(title) { | |
title = (title + '').trim(); | |
if (title) { | |
Manager.updateWidgetTitle(this.widgetFrameworkPath, title); | |
this.lastWidgetTitle = title; | |
} | |
return this; | |
}, | |
getTitle: function() { | |
return this.lastWidgetTitle; | |
}, | |
/** | |
* Append something to widget title. If empty value passed (or no value), then we restore original title | |
* @param {String} [text=''] | |
* @param {Boolean} [spaceBefore=true] | |
* @returns this | |
*/ | |
appendToTitle: function(text, spaceBefore) { | |
if (!spaceBefore) spaceBefore = true; | |
this.setTitle(this.actualSettings.title + (!text ? '' : (!spaceBefore ? text : ' ' + text))); | |
return this; | |
}, | |
setAsOfDate: function(asOfDate) { | |
if (asOfDate) WindowTitleForDate.addDateToTitle(this.getNodeId(), asOfDate, true); | |
else WindowTitleForDate.removeDateFromTitle(this.getNodeId()); | |
this.lastAsOfDate = asOfDate; | |
return this; | |
}, | |
getAsOfDate: function() { | |
return this.lastAsOfDate || ''; | |
} | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'jsclass/class', | |
'./AbstractPlugin', | |
'Shared/WidgetFoundation/Util', | |
'async', | |
// Filters preloading | |
'Shared/WidgetFoundation/CustomFilter/ApplyButton', | |
'Shared/WidgetFoundation/CustomFilter/Input', | |
'Shared/WidgetFoundation/CustomFilter/Select' | |
], function( | |
Class, AbstractPlugin, Util, Async, | |
// Preloaded filters | |
ApplyButtonFilter, InputFilter, SelectFilter) { | |
return new Class(AbstractPlugin, { | |
// Shortcuts | |
preloadedCustomFilters: { | |
ApplyButton: ApplyButtonFilter, | |
Input: InputFilter, | |
Select: SelectFilter | |
}, | |
filters: null, | |
initialize: function(widget, args, callback) { | |
this.callSuper(widget, args); | |
this.filters = []; | |
// Preserve context | |
var self = this; | |
// Async filter loading (some files aren't loaded yet) | |
Async.each(args.filters, function(filter, cb) { | |
// Constructed filter (yeah, class that not from WF-package can be used) | |
if (filter.setCustomFilterPlugin) { | |
filter.setCustomFilterPlugin(self); | |
self.filters.push(filter); | |
cb(); | |
} | |
else { | |
// Filter name only, without any parameters | |
if ('string' == typeof filter) filter = [filter, {}]; | |
// Filter with parameters [filterName, parametersObject] | |
if (2 === filter.length && 'object' == typeof filter) { | |
// Here is args structure, example - ['SomeFilter', { title: 'custom title' }] | |
var filterName = filter[0], | |
filterArgs = filter[1]; | |
var onLoad = function (filterClass) { | |
var filterObject = new filterClass(filterArgs); | |
filterObject.setCustomFilterPlugin(self); | |
self.filters.push(filterObject); | |
setTimeout(cb, 10); | |
}; | |
// File already loaded | |
if (self.preloadedCustomFilters[filterName]) onLoad(self.preloadedCustomFilters[filterName]); | |
// Or load class by require-js lib | |
else require([filterName], onLoad); | |
} | |
else throw new Error('Args type is unknown!'); | |
} | |
}, function() { | |
// Initial values | |
widget.listenEvent(widget.eventsMap.stateLoaded, function() { | |
Util.forEach(self.filters, function(i, filter) { | |
if (filter.isPersistent()) { | |
filter.setValue(widget.getFromState( | |
'customFilter.' + filter.getName() + self.getContextUID(), | |
filter.getDefaultValue() | |
)).dataInitialized(); | |
} | |
}); | |
}); | |
// HTML | |
widget.listenEvent(widget.eventsMap.viewInitialized, function() { | |
var filtersNode = widget.getNodeBodyContainer().find('.filters'); | |
Util.forEach(self.filters, function(i, filter) { | |
var node = $(filter.getHTML()); | |
filter.nodeCreated(node); | |
filtersNode.append(node); | |
filter.nodeRendered(); | |
}); | |
}); | |
// Affect on data request | |
widget.listenEvent(widget.eventsMap.dataRequestParametersGenerated, function(parameters) { | |
Util.Object.merge(parameters.pager.customFilters, (function() { | |
var filters = {}; | |
Util.forEach(self.filters, function (i, filter) { | |
if (filter.hasValue()) { | |
filters[filter.getName()] = filter.getValue(); | |
} | |
}); | |
return filters; | |
})()); | |
}); | |
callback(); | |
}); | |
}, | |
/** | |
* Store values in widget state | |
* | |
* @returns this | |
*/ | |
persistValues: function() { | |
var self = this; | |
Util.forEach(self.filters, function(i, filter) { | |
if (filter.isPersistent()) { | |
self.getWidget().setToState( | |
'customFilter.' + filter.getName() + self.getContextUID(), | |
filter.getValue() | |
); | |
} | |
}); | |
this.getWidget().saveStateIfChanged(); | |
return this; | |
}, | |
/** | |
* Reload widget data (only update) | |
* | |
* @returns this | |
*/ | |
reloadData: function() { | |
this.getWidget().reloadGridData(); | |
return this; | |
}, | |
/** | |
* Combined logic | |
* | |
* @returns this | |
*/ | |
persistAndReloadData: function() { | |
this.persistValues().reloadData(); | |
return this; | |
}, | |
getContextUID: function() { | |
return ''; | |
} | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Widget data model | |
* | |
* @author Sermik 2014, And <[email protected]> | |
*/ | |
define(['Shared/WidgetFoundation/WidgetViewModel'], function (Model) { | |
return Model.constructor({ | |
columns: { | |
AccountNumber: { type: Model.FIELD_TYPE.ACCOUNT_NUMBER, title: 'Account' }, | |
RepCode: { type: Model.FIELD_TYPE.REP_ID, title: 'Rep' }, | |
AccountName: { type: Model.FIELD_TYPE.STRING, title: 'Name' }, | |
OpenDate: { type: Model.FIELD_TYPE.DATE }, | |
Restriction: { type: Model.FIELD_TYPE.STRING } | |
} | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Widget itself | |
* | |
* @author Sermik 2014, And <[email protected]> | |
*/ | |
define(['Shared/WidgetFoundation/GridWidget', 'Shared/WidgetFoundation/Util'], function (GridWidget, Util) { | |
return GridWidget.loader({ | |
default: { | |
title: 'Restricted Accounts', | |
// Minimum size | |
size: { width: 1000 }, | |
// Widget custom filters | |
filter: { | |
customFilters: [ | |
['Select', /* input type */ { | |
title: 'Restriction Type:', | |
// Input name (must match with server model) | |
name: 'restrictionType', | |
values: [ | |
["All", "All"], | |
["111175", "An Employee of Other Brokerage Firm-Rule 407"], | |
["111185", "Abandoned Property"], | |
["111165", "BRR"], | |
["111144", "CBG Missing Documents"], | |
["111134", "CP Baker - contact margin"], | |
["111153", "Dawson James"], | |
["111121", "Delinquent Documents"], | |
["111122", "Date of Birth/UTMA"], | |
["111142", "EJ Sterling"], | |
["111125", "Equifax Mismatch - AML"], | |
["111133", "FINRA Rule 2111"], | |
["111141", "4 Points Capital-Gene Murphy"], | |
["111155", "Fraud Alert"], | |
["111136", "Lead/Generation Accounts"], | |
["111124", "John Thomas Missing Documents"], | |
["111135", "Margin"], | |
["111143", "Meyers"], | |
["111145", "New Accounts"], | |
["111126", "PCG-San Francisco - contact NA"], | |
["111154", "WRP"] | |
] | |
}], | |
// Button, which send data to server and persist values | |
'ApplyButton' | |
] | |
} | |
} | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment