I am working on a web app that uses requireJS and angular. The solution is fine however I am having issues after optimization.
The way I build the application is by way of r.js. I execute it targeting my main.js that has a define() statement in it that points to all the other files in the solution as dependencies. It then generates a new main.js in my bin/ directory with all the js files it referenced concatenated into the one main.js file. So far so good.
However when I try to load the app in the browser with the optimized js, I notice that none of the define() callbacks ever get called, not even the ones with no dependencies ([]) As far as my knowledge of requireJS, modules' callbacks are executed as soon as all dependencies are resolved.
This all works just fine when the js files are all in their respective locations, with anonymous names, pre build. Its the same exact js just all in one file, so I have no idea what could be different. Other than the optimizer gave the modules names (which is what its supposed to do)
The only thing I can think of is that I am missing a bootstrapping 'require' call to the main module (which is at the bottom of the following optimized file) but I don't have any call to 'require' in my non-built solution and it works just fine.
My script that calls r.js is in a directory called 'build/' which is a sibling of 'js/' which is the root directory of where my js is.
Example of my issue: that first define('../js/common/module',[],function()... its callback never gets called despite the fact that there are no dependencies.
Does anyone know what the issue is? Any help would be much appreciated.
define('../js/common/module',[], function () {
return {
app: angular.module('common', []),
ngContext: true
}
});
define('../js/customer_account_list/module',['../common/module'], function () {
return {
app: angular.module('customer_account_list', ['common']),
ngContext: true
}
});
define('../js/mod',['./customer_account_list/module'], function () {
angular.module('app', ['customer_account_list']);
});
define('../js/common/service/app_config',['../module'], function (module) {
/**
* #class appConfigService
* #memberOf common.service
* #description calls back to the server to get the application configuration
**/
var appConfigService = function () {
url = window.location.protocol + '//' + window.location.host + window.location.pathname + 'config.json';
var configReq = new XMLHttpRequest();
configReq.open("GET", url, false);
configReq.send();
return JSON.parse(configReq.response);
}
if (module.ngContext) {
module.app.service('appConfig', appConfigService);
}
});
define('../js/common/service/feature_manager',['../module'], function (module) {
/**
* #class featureManagerServ
* #memberOf common.service
* #description manages the set of features in the product portal
**/
function featureManagerServ(appConfig) {
this.featuresEnabled = {
'customer_account_list': appConfig.features['customer_account_list']
};
/**
* #function
* #memberOf common.service.featureManagerServ
* #param {string} featureKey - feature identifier
* #description computes whether or not the feature should be enabled
**/
this.featureEnabled = function (featureKey) {
return !!this.featuresEnabled[featureKey];
};
/**
* #function
* #memberOf common.service.featureManagerServ
* #param {string} featureKey - feature identifier
* #param {Object} directive - Ng directive
* #description handles whether or not the feature will be bootstrapped
**/
this.bootstrapFeature = function (featureKey, directive) {
if (this.featureEnabled(featureKey)) {
return directive;
} else {
}
};
};
if (module.ngContext) {
module.app.service('featureManager', ['appConfig', featureManagerServ]);
}
});
define('../js/customer_account_list/directives/customer_account_list_ctrl',[], function () {
function customerAccountListCtrl($scope, customerAccounts) {
$scope.customerAccounts = customerAccounts.getCustomerAccounts();
$scope.onAccountClick = function (ind) {
var s = 0;
}
}
return ['$scope', 'customerAccounts', customerAccountListCtrl];
});
define('../js/customer_account_list/directives/customer_account_list',['../module', './customer_account_list_ctrl'], function (module, ctrl) {
/**
* #class customerAccountList
* #memberOf customer_account_list.directive
* #description customer account list component
**/
module.app.directive('customerAccountList', ['featureManager', function (featureManager) {
return featureManager.bootstrapFeature('customer_account_list', {
restrict: 'E',
templateUrl: 'js/customer_account_list/views/customer_account_list.html',
scope: {
url: '='
},
controller: ctrl
});
}]);
});
define('../js/customer_account_list/service/customer_accounts',['../module'], function (module) {
/**
* #class customerAccountsServ
* #memberOf customer_account_list.service
* #description provides list of customers user is authenticated to view/edit
**/
function customerAccountsServ($http, appConfig) {
/**
* #function
* #memberOf customer_account_list.service.customerAccountsServ
* #description provides list of customers user is authenticated to view/edit
**/
this.getCustomerAccounts = function () {
return ['AcmeFood', 'AcmeCoffee','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9'];
}
}
if (module.ngContext) {
module.app.service('customerAccounts', ['$http', 'appConfig', customerAccountsServ]);
}
});
define('../js/main.js',['./mod',
'./common/module',
'./common/service/app_config',
'./common/service/feature_manager',
'./customer_account_list/module',
'./customer_account_list/directives/customer_account_list',
'./customer_account_list/directives/customer_account_list_ctrl',
'./customer_account_list/service/customer_accounts'],
function () {
angular.element().ready(function () {
angular.bootstrap(document, ['app'], {
strictDi: false
});
});
});
Related
I am trying to build a JS file to place in the file cabinet to reference my most used functions I constantly rebuild. I have been able to access it by placing the script in the file cabinet and using the #NAmdConfig to reference the functions. However, I cannot access the NetSuite modules in these scripts. I cut most of the function off in my example, but if I can return that to my original Map/Reduce script that will suffice. How can I have a third party script of my most used functions while still having access to the NetSuite modules?
/**
* #NApiVersion 2.1
* #NModuleScope public
*/
var MattsFunctions = {
dynamicTransactionSearch:
function (sentId) {
var thisRecord = record.load({
type: record.Type.SALES_ORDER,
id: sentId
})
return thisRecord.id
}
}
I have also tried
/**
* #NApiVersion 2.1
* #NModuleScope public
*/
define(['N/search', 'N/record'],
(search, record) => {
var exports = {};
var MattsFunctions = {
dynamicTransactionSearch:
function (sentId) {
var thisRecord = record.load({
type: record.Type.SALES_ORDER,
id: sentId
})
return thisRecord.id
}
}
exports.MattsFunctions = MattsFunctions
return exports
})
Figured it out. Simply pass the module over in the function you're calling, of course!
I have a Vue component with one method...
methods: {
launchOpinionLab () {
initOpinionLab({
clientId: this.clientId,
flow: this.flow,
srcCorrelationId: this.srcCorrelationId
})
window.OOo.inlineFeedbackShow()
}
initOpinionLab() is a exported function as such
initOpinionLab.js
/**
* Initializes the OpinionLab library with custom data.
*
* #param {Object} data - any data we want to attach to user feedback submissions
*/
export default function initOpinionLab (data) {
const opinionLab = window.OOo
/**
* Callback to launch the feedback comment card.
* This assigns our custom data to the OpinionLab instance.
*
* #param {Event} event - window event
*/
opinionLab.inlineFeedbackShow = (event) => {
let replacePattern = '://' + window.location.host
if (window.location.host !== 'checkout.mastercard.com') {
replacePattern = '://test.checkout.mastercard.com'
}
opinionLab.oo_feedback = new opinionLab.Ocode({
referrerRewrite: {
searchPattern: /:\/\/[^/]*/,
replacePattern: replacePattern
},
customVariables: data
})
// Now that oo_feedback has been re-initialized with the custom
// var and context of the current page, launch the comment card
opinionLab.oo_launch(event, 'oo_feedback')
}
/**
* Launches opinionLab.
*
* #param {Event} event
* #param {Object} feedback - opinionLab-structured feedback object
*/
opinionLab.oo_launch = (event, feedback) => {
opinionLab[feedback].show(event || window.event)
}
}
At the top of my unit test is the mock of that module, jest.mock('./initOpinionLab', () => jest.fn()).
My goal is to assert that initOpinionLab({}) is called with the correct props. When I try to spy on it, I get "Cannot spy the initOpinionLab property because it is not a function; undefined given instead". How do I write a robust test for this?
Or, what if I moved initOpinionLab() to mounted? Can I better test it then?
component.spec.js
it('[positive] initOpinionLab should be initialized with props' , () => {
const initOpinionLab = jest.fn()
jest.spyOn(wrapper.vm, 'initOpinionLab')
wrapper.vm.launchOpinionLab()
expect(initOpinionLab).toHaveBeenCalled()
})
So I'm trying to recreate this app on SAP Web IDE:
But I'm continuously getting this error:
This is my App.Controller.js code:
sap.ui.define([
"pt/procensus/ui5rv/controller/BaseController",
"sap/ui/model/json/JSONModel"
], function (BaseController, JSONModel) {
"use strict";
return BaseController.extend("pt.procensus.ui5rv.controller.App", {
onInit : function () {
var oViewModel,
fnSetAppNotBusy,
oListSelector = this.getOwnerComponent().oListSelector,
iOriginalBusyDelay = this.getView().getBusyIndicatorDelay();
oViewModel = new JSONModel({
busy : true,
delay : 0
});
this.setModel(oViewModel, "appView");
fnSetAppNotBusy = function() {
oViewModel.setProperty("/busy", false);
oViewModel.setProperty("/delay", iOriginalBusyDelay);
};
this.getOwnerComponent().oWhenMetadataIsLoaded.
then(fnSetAppNotBusy, fnSetAppNotBusy);
// Makes sure that master view is hidden in split app
// after a new list entry has been selected.
oListSelector.attachListSelectionChange(function () {
this.byId("idAppControl").hideMaster();
}, this);
// apply content density mode to root view
this.getView().addStyleClass(this.getOwnerComponent().getContentDensityClass());
}
});
}
);
This is my Base.Controller.js code:
/*global history */
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/routing/History"
], function(Controller, History) {
"use strict";
return Controller.extend("pt.procensus.ui5rv.controller.BaseController", {
/**
* Convenience method for accessing the router in every controller of the application.
* #public
* #returns {sap.ui.core.routing.Router} the router for this component
*/
getRouter: function() {
return this.getOwnerComponent().getRouter();
},
/**
* Convenience method for getting the view model by name in every controller of the application.
* #public
* #param {string} sName the model name
* #returns {sap.ui.model.Model} the model instance
*/
getModel: function(sName) {
return this.getView().getModel(sName);
},
/**
* Convenience method for setting the view model in every controller of the application.
* #public
* #param {sap.ui.model.Model} oModel the model instance
* #param {string} sName the model name
* #returns {sap.ui.mvc.View} the view instance
*/
setModel: function(oModel, sName) {
return this.getView().setModel(oModel, sName);
},
/**
* Convenience method for getting the resource bundle.
* #public
* #returns {sap.ui.model.resource.ResourceModel} the resourceModel of the component
*/
getResourceBundle: function() {
return this.getOwnerComponent().getModel("i18n").getResourceBundle();
},
/**
* Event handler for navigating back.
* It checks if there is a history entry. If yes, history.go(-1) will happen.
* If not, it will replace the current entry of the browser history with the master route.
* #public
*/
onNavBack: function() {
var sPreviousHash = History.getInstance().getPreviousHash();
if (sPreviousHash !== undefined) {
// The history contains a previous entry
history.go(-1);
} else {
// Otherwise we go backwards with a forward history
var bReplace = true;
this.getRouter().navTo("master", {}, bReplace);
}
}
});
});
My App Folders:
And I can't understand why is this happening. I've already removed the 'then' part and it gives me more errors... :/
Any help will be very much appreciated :)
Can you try this? At least this is how it works in my App.controller:
this.getOwnerComponent().getModel().metadataLoaded()
.then(fnSetAppNotBusy, fnSetAppNotBusy);
I'm currently working on a website with vue.js, and I use vue-route.
There's a subroute (/blog/post-slug) that load a script (Prism: http://prismjs.com/) and fires it in the ready() state :
import Prism from 'prismjs'
module.exports = {
Route: {
waitForData: true
},
data () {
return {
post: { }
}
},
ready () {
Prism.highlightAll()
}
}
When I reach the page from a link inside the site, it’s all good, loaded and working, the result is ok in the page.
But if I reload the page or access it with a direct link from an external link, it’s not good.
Here’s my route config, if it helps:
/**
* Router config
*/
module.exports = {
/**
* Config
* #type {Object}
*/
config: {
hasbang: false,
history: true,
saveScrollPosition: true,
linkActiveClass: 'site-menu__link--active',
transitionOnLoad: true
},
/**
* Before route starts transitioning
* #param {Object} options.from Route we are transitioning from
* #param {Object} options.to Route we are transitioning to
* #param {Function} options.next Progress to the next step of the transition
* #param {Function} options.abort Cancel / Reject the transition
* #param {Function} options.redirect Cancel and redirect to a different route
* #return {void}
*/
before ({from, to, next, abort, redirect}) {
next()
},
/**
* After route has transitioned
* #param {Object} options.from Route we are transitioning from
* #param {Object} options.to Route we are transitioning to
* #return {void}
*/
after ({from, to}) {
if (typeof to.title !== 'undefined') {
document.title = to.title
}
}
}
I guess something in particular happen when the view is loaded from inside the app, and not directly, but can’t find what.
What am I missing?
Thanks in advance for any hint.
I am attempting to use wordpress to build a website that integrates google maps. I am doing some overlays with the maps and use the google developers API and Python to make the appropriate javascript. I have successfully written the js files and Python necessary to accomplish this.
My website is built in Worpress and I would like add a page (not the home page) that has n links and each one would populate a box with the corresponding map. I can take care of the layout and design issues but I am at a loss on how to:
a) Include the javascript as a file that
b) gets called upon clicking the link and thus populates that map without calling a new page
That is, the javascript is HUGE because it may include thousands of lat/lon points. Therefore including n of these written into the header is unreasonable. I want to simply call it from filename.js when the link is clicked.
There is a plugin that allows me to include whatever I want in the header. So, if I can find out where to put the *.js files (or txt file) in the directory tree and how to have the corresponding file activated upon click I should be good. Thanks!
This Display different maps with onClick event - Google Maps V3. kind of helps with doing an on-click display but everyone's solution was to make one map. I cannot do that. I am overlaying vast amounts of data.
Here is a way you can get that done. (Jump down to the get started part of the script.)
For brevity, I've included a bunch of scripts in one 'file', but you'll want to break them in to individual files.
You may also need to try the html and js in jsbin js bin example, b/c SO may or may not allow the dynamic loading of js.
(function(undefined) {
/**
* #author (#colecmc)
* #method turn collection into an array
* #param {object} collection - NodeList, HTMLCollection, etc. Should have an "item" method and/or a "length" property
*/
ToArray = collection => Array.prototype.slice.call(collection);
/** \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ **/
Observer = (function(undefined) {
/**
* pub sub
*/
'use strict';
var subUid = -1;
return {
topics: {},
subscribe: function(topic, func) {
/**
* #param {string} topic
* #param {function} func
* #returns {string} - a token such as '3'
* #example Observer.subscribe('any-valid-string',function(name,resp){
console.log(resp.prop);
});
*/
if (!Observer.topics[topic]) {
Observer.topics[topic] = [];
}
var token = (++subUid).toString();
Observer.topics[topic].push({
token: token,
func: func
});
return token;
},
publish: function publish(topic, args) {
/**
* #param {string} topic
* #param {object} args
* #returns {boolean} - true if topic is valid, false otherwise
* #example Observer.publish('any-valid-string',{
prop: 'this is a test'
});
*/
if (!Observer.topics[topic]) {
return false;
}
setTimeout(function() {
var subscribers = Observer.topics[topic],
len = subscribers ? subscribers.length : 0;
while (len--) {
subscribers[len].func(topic, args);
}
}, 0);
return true;
},
unsubscribe: function unsubscribe(token) {
/**
* #param {string} token - value should be saved from the original subscription
* #example Observer.unsubscribe('2');
* #example Observer.unsubscribe(member); - where member is the value returned by Observer.subscribe();
*/
var m,
forEachTopic = function(i) {
if (Observer.topics[m][i].token === token) {
Observer.topics[m].splice(i, 1);
return token;
}
};
for (m in Observer.topics) {
if (Observer.topics.hasOwnProperty(m)) {
Observer.topics[m].forEach(forEachTopic);
}
}
return false;
}
};
}(undefined));
/** \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ **/
SetAttributes = function(el, attrs) {
/**
* #author (#colecmc)
* #method simple for in loop to help with creating elements programmatically
* #param {object} el - HTMLElement attributes are getting added to
* #param {object} attrs - object literal with key/values for desired attributes
* #example SetAttributes(info,{
* 'id' : 'utswFormInfo'
* 'class' : 'my-class-name'
* });
*/
'use strict';
var key;
for (key in attrs) {
if (attrs.hasOwnProperty(key)) {
el.setAttribute(key, attrs[key]);
}
}
return el;
};
/** \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ **/
GetScript = function(url, fullPath) {
/**
* #author (#colecmc)
* #version 1.0.4
* #requires Swlxws.SetAttributes, Swlxws.Observer
* #method dynamically add script tags to the page.
* #param {string} url - relative path and file name - do not include extension
* #param {string} fullPath - absolute path
* #example GetScript('myLocalScript');
* #example GetScript('','https://www.google-analytics.com/analytics.js');
*/
'use strict';
function onLoad(event) {
var result;
if (event.type === 'load') {
result = 1;
} else {
result = -1;
}
Observer.publish('get-script-onload-complete', {
successful: result,
eventData: event
});
}
var JSPATH = '/js/',
/* or where ever you keep js files */
el = document.createElement('script'),
attrs = {
defer: true,
src: null,
type: 'text/javascript'
};
/** look for a string based, protocol agnostic, js file url */
if (typeof fullPath === 'string' && fullPath.indexOf('http') === 0) {
attrs.src = fullPath;
}
/** look for any string with at least 1 character and prefix our root js dir, then append extension */
if (typeof url === 'string' && url.length >= 1) {
attrs.src = JSPATH + url + '.js';
}
SetAttributes(el, attrs);
el.addEventListener('load', onLoad);
el.addEventListener('error', onLoad);
document.body.appendChild(el);
return el;
};
/** \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ **/
/**
* Get Started
*/
function onClick(event) {
GetScript('', event.target.dataset.namespaceUrl);
}
Observer.subscribe('get-script-onload-complete', function(name, resp) {
/** check to make resp is what you expect, ie: the correct script loaded */
/** then it is safe to use */
});
ToArray(document.querySelectorAll('.load-scripts')).map(script => script.addEventListener('click', onClick, false));
}(undefined));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>How to include js files in header of wordpress pages that are activated on-click</title>
</head>
<body>
Load Google Analytics
</body>
</html>
You can use the function wp_enqueue_script() to load the necessary JS files on only the templates you want.
As for your large data set, I recommend that you cache it in an external .json file and use wp_enqueue_script() to load it only when necessary.
Well if the onclick event suggestion is pretty much what you want and you are just concerned about the large amount of data. Then there are a few ways to tackle it. I am not sure if the dataset is a js file or php/json files but i came across a similar issue on one of my projects, dont remember properly but i was doing something with maxmind's ip/location data set.
So i just splitted the large file into 3 smaller ones. Then i looped through each of the file and if the stuff that i was looking for was found in the file then i just breaked out. And definitely as Brian suggested caching and using a CDN would help a lot.