JS namespacing and page-load - javascript

I've read about how to make a JS namespace, but my question is how can I make sure the functions inside would only happen on page load?
i.e. instead of:
$(document).ready(function () {...});
(or any other lib then jquery).
also - is there a way to control what will launch on page load and what would before?
Thank you!:)

The following example uses an immediate-function to encapsulate the Code and registers an event-handler on the event DOMContentReady which fires when the Browser has the DOM ready but bevor Images are loaded.
(function () {
'use strict';
var
init = function () {
window.console.info('init()');
};
window.addEventListener('DOMContentReady', init, false);
}());
The immediate-function gets executet as soon as the browser loads the code. From that point there are different events on which further code-execution can be scheduled.
Without using a framework like jquery, which puts some effort in this toppic, you have to handle different events in different browser by your own.

put this code out of jquery code
var MyReallyCoolLibrary = {
awesome: "stuff",
doSomething: function() {
},
doAnotherThing: function() {
}
};
MyReallyCoolLibrary.awesome;
alert(MyReallyCoolLibrary.awesome);

Related

Drupal 8 Drupal.behaviors without jquery

Is there a way to add drupal behaviors to a theme without invoking jquery in Drupal 8?
This is what the tutorial show:
(function ($, Drupal) {
Drupal.behaviors.myModuleBehavior = {
attach: function (context, settings) {
$('input.myCustomBehavior', context).once('myCustomBehavior').each(function () {
// Apply the myCustomBehaviour effect to the elements only once.
});
}
};
})(jQuery, Drupal);
But i want to use pure js without invoking jquery, something like this:
(function (Drupal) {
Drupal.behaviors.myModuleBehavior = {
attach: function (context, settings) {
context.querySelector('input.myCustomBehavior').classList.add('processed');
}
};
})(Drupal);
I understand that modules may invoke jquery on their own but i still would like to remove it from my scripts if possible and still have it run after ajax events.
Thanks
Have you tried it?
I also did not know this, so went investigating.
It seems that Drupal no longer relys on jQuery's document.ready to fire behaviors.
As seen in this change record.
This leads me to believe that the second code block that you posted should work (with Drupal 8.x).

The Url of dialog box does not work with angular.bootstrap (infinite $digest Loop)

I have a mean-stack website. I want to use ExecuteFunction to bind a button to launch this website in a Dialog box:
function doSomethingAndShowDialog(event) {
clickEvent = event;
Office.context.ui.displayDialogAsync("https://localhost:3000/try", {}, function () {})
}
Clicking on the button opens a dialog box with the following url, it does show the content of the page:
https://localhost:3000/try?_host_Info=excel|web|16.00|en-us|7fe9b4e9-d51e-bea5-d194-c817bc5ed4bc|isDialog#%2Ftry%3F_host_Info=excel%7Cweb%7C16.00%7Cen-us%7C7fe9b4e9-d51e-bea5-d194-c817bc5ed4bc%7CisDialog
However, in the console, there are Error: $rootScope:infdig
Infinite $digest Loop at angular.bootstrap(document, ['myapp']):
var wait = setTimeout(myFunction, 1000);
Office.initialize = function (reason) {
$(document).ready(function () {
angular.bootstrap(document, ['myapp'])
console.log("bootstrapped inside Office.initialize");
clearTimeout(wait);
})
}
function myFunction () {
$(document).ready(function () {
angular.bootstrap(document, ['myapp'])
console.log("bootstrapped outside Office.initialize");
})
}
app = angular.module("myapp", []);
app.config(...);
app.controller(...);
If we just open https://localhost:3000/try in a browser, there is no error.
Does anyone know why that long url did not work with angular.bootstrap? How could we fix this?
Edit 1: a screenshot of the console for https://localhost:3000/try?_host_Info=excel.... Note that neither bootstrapped inside Office.initialize nor bootstrapped outside Office.initialize is displayed. But If I run https://localhost:3000/try in a browser, I will only see bootstrapped outside Office.initialize, when I call it from an Excel client, I will only see bootstrapped inside Office.initialize.
It sounds like you're trying to wire up a page that can operate as either an add-in or a stand-alone page. Whenever possible it is best to maintain separate views for each use case. If nothing else, it makes everything a lot more straight forward. Combining them is likely creating far more overhead and headache that it's worth.
Part of your issue here is that you've got two separate code paths and you're assuming only one path will execute at a time. When loaded in a browser this is true, it will simply ignore the Office.initialize function. When loaded within Office however it will execute both paths. One will be executed by Office, the other will be executed by setTimeOut after 1 second.
If you have two distinct code paths where only one is ever executed, you need to test to determine if you're operating as an add-in or as a standalone page. This is where those query parameters come into play. If you have a _host_Info query parameter defined then you're operating within Office. For example:
if (getParameterByName('_hostInfo')) { // _hostInfo is defined
Office.initialize = function (reason) {
$(document).ready(function () {
angular.bootstrap(document, ['myapp'])
console.log("bootstrapped inside Office.initialize");
});
}
}
else { // _hostInfo is not defined
$(document).ready(function () {
angular.bootstrap(document, ['myapp'])
console.log("bootstrapped outside Office.initialize");
})
}
Note that getParameterByName() here is a function pulled from this answer. You could use any method you prefer however.

Using jQuery / javascript How to check if JS file ( SP.JS) is already called in a page?

I want to check if a particular JS file is already loaded in document.ready.
Something like this:
if(file already called/loaded) { // my code }
else {//some other code}
The JS File is not any plugin.
Its basically a JS file related to SharePoint like Sp.JS.
We just know the file name.
[Update - Added the code ]
I have added the below code and it throws an error in console : SP.Runtime.js is already loaded.
If I remove the loading of SP.Runtime.js my code doesnt work in some pages where Runtime.Js is not loaded by default.
$(document).ready(function() {
var scriptbase = _spPageContextInfo.webServerRelativeUrl + "/_layouts/15/";
$.getScript(scriptbase + "init.js",
function() {
$.getScript(scriptbase + "SP.Runtime.js",
function() {
$.getScript(scriptbase + "SP.js",
function() {
$.getScript(scriptbase + "SP.Taxonomy.js",
function() {
context = SP.ClientContext.get_current();
// My custom function //
});
});
});
});
});
Please suggest.
Thanks
SharePoint JavaScript Library, in particular SP.SOD namespace contains methods for loading/ensuring JavaScript files.
SP.SOD.executeOrDelayUntilScriptLoaded - executes the specified
function if the file containing it is loaded, for example:
ExecuteOrDelayUntilScriptLoaded(myfunc, "SP.js");
function myfunc()
{
}
In that case myfunc will be invoked after sp.js file is loaded
SP.SOD.executeFunc - ensures that the specified file that
contains the specified function is loaded and then runs the
specified callback function, for example:
SP.SOD.executeFunc('sp.js', 'SP.ClientContext',
function (){
//your code goes here...
});
The behavior is similar to previous example but the main difference
that this function also supports load on demand scripts.
If you only need to ensure that specific native JS files of SharePoint are loaded before executing your code then Vadim's answer is all what you need, however if you require to ensure the loading of all page elements including all JS files then you should use window.onload.
Please take a look at this page where people discuss about the differences between windows.onload and $(document).ready().
window.onload vs $(document).ready()
UPDATE:
In case you are using your code in any page within SharePoint then you don't need to force the loading of native JS files, you only need to execute your code at the right moment of the page load process.
Try using $(window).load or window.onload instead of $(document).ready, by example:
$(window).load(function(){
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function (){
context = SP.ClientContext.get_current();
//your code goes here...
});
});

jquery-extension not executing in chrome app

I've encountered a strange problem with my chrome app i'm developing at the moment.
I want to use the "knob" extension to use it for a alarm-clock slider (to set the time)
This wouldn't be a really difficult matter, wouldn't it be for the restrictions and strange issues found while programming a chrome app.
In my index.html file I included the jquery library and the knob extension. And that is where the problems started. Somehow, my scripts only can use the Id's of elements that are above them. So when I include the tags between the tags, nothing executes, if I put them after the first tags they only work with the things that are in this div container. thats why I put the script just before the tag. That works well for "normal" javascript usability. But because I have a that referes to a jquery function (for the knob) the jquery library should be already loaded before the function gets executed (if not, it just doesn't work). I tried to get a workaround by using these posibilities:
document.onload=test();
function test(){
$(function() {
$(".dial").knob();
});
}
document.onload=test();
$(function test() {
$(".dial").knob();
});
}
document.onload=$(function() {
$(".dial").knob();
});
}
well.... It didn't work. I also tried window.onload, with the same reuslt. does someone have a solution? It would be of great help.
Thank you,
neissen
Try like this:
$(function() { //document ready function
function test(){ //inside the ready function
$(".dial").knob();
}
test(); // and call the function here
});
Your Problems:
jQuery may not be loaded but you used some vanilla JS to handle jQuery, which will cause errors.
May be related to global and local.
For the external scripts, functions are only fired locally, which means the global object which contains the html won't be able to be accessed.
To make a global function and a jQuery library - JS:
if ("undefined" === typeof jQuery) {throw new Error("This library requires jQuery"); }
$(function() {
window.myFunction = function() {
doSomething();
}
doSomething();
})
Works calling from HTML - HTML:
<script>
$(function() {
doSomething();
})
</script>
Above is the safest way to approach a jQuery library. The $(function() {... part means exactly the same as $( document ).ready(function() {..., execute if loaded and ready, ensures the browser knows how to deal with all the functions used.

Javascript - Use onload event , or not

I'm coding a script that will be used on several websites as a plugin. I have to use only Javascript, no framework. I'm asking myself, what is the best way to load my script without causing any trouble with other scripts or frameworks that can be loaded on these websites.
I thought to do a global function where i call the functions I want to use, and I put this function on the window.load event, like this :
<script>
var global = function(){
object.domain.function1();
object.domain.function2(param1, param2);
object.domain.function3(1);
}
(function(){
if(document.addEventListener){
document.addEventListener('load',global, false);
}
if(document.attachEvent){
document.attachEvent('onload',global);
}
})();
</script>
Or simply :
<script>
object.domain.function1();
object.domain.function2(param1, param2);
object.domain.function3(1);
</script>
Of course, I need some elements are loaded on my page.
Thanks in advance.
If you're ok with putting javascript inside the <body> tag then a fairly reliable way of running javascript after the entire page has loaded is placing your javascript in <script> tags at the very bottom of the page.
It's not my preferred way of handling this issue, but if using the onload event is not working quite right for you this would be a good next step.
what is the best way to load my script without causing any trouble with other scripts or frameworks
The things you need to consider are, are you..
polluting the namespace
obstructing another script
The second point is easy to work around, .addEventListener supports adding many listeners for the same event which won't overwrite each other. There are two different events you might be interested in, 'load' on window and 'DOMContentLoaded' on document. You can always put a <script> at the very end of <body> but I personally don't like doing this because you're mixing HTML with JavaScript or changing the DOM tree.
For the first point, this can be done via the use of anonymous functions and, should you need to occupy the namespace, keeping all of your variables and methods inside one object to minimise your impact.
Putting all this together you may end up with something like this
var myObjectName = { // everything in one object in global namespace
domain: {
function1: function () { /*...*/ },
function2: function () { /*...*/ },
function3: function () { /*...*/ }
}
};
(function (fn) {
if (window.addEventListener) {
window.addEventListener('load', fn, false);
}
else if (window.attachEvent) { // Consider if support for `.attachEvent` is really necessary, people need to move on.
window.attachEvent('onload', fn);
}
})(function () { // pass your function anonymously
myObjectName.domain.function1();
myObjectName.domain.function2(param1, param2);
myObjectName.domain.function3(1);
});

Categories