How can MyWebsite send jQuery or AngularJS javascript package that can use website and website without conflict?

Let's say I have a MyWebsite website where you can create content for a call-to-action window that should appear on another website, WebsiteA and other websites that choose our solution without using an iframe.

How to create this box using jQuery or AngularJS without conflicts, not knowing what the client has on their web page, they simply import our some_script.js , set some settings, and this. Most importantly, we cannot spoil the client side (obviously), and the technologies that the client uses do not spoil our super-duper box.

I would like to see a working example. This is difficult (I think), so please take more time to think before answering if you have not solved such a problem. Appreciate the help guys!

+5
source share
8 answers

RequireJS allows you to create expendable JQuery / AngularJS (AMD) applications without worrying about version conflicts

Instead of worrying about noconflict's library, RequireJS creates a separate area with a sandbox / variable outside the global with AMD . Only included versions are available in AMD .

AMD - Asynchronous module definitions are self-nesting applications with their own area for libraries. Self-Encolsure is similar to a namespace, complete absence of conflicts. For more information about using modules, see WHY WEB MODULES .

AngularJS example, create an AngularMain.js file:

 require.config({ baseUrl: "js", paths: { 'angular': '//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min', 'angularAMD': 'lib/angularAMD.min', 'ngload': 'lib/ngload.min' }, shim: { 'angularAMD': ['angular'], 'angular-route': ['angular'] }, deps: ['AngularApp'] }); 

Now require.config indicated that AngularApp.js should also be included (as you will see, RequireJS usually assumes the ".js" extensions), with dependencies on angular.js and angular -route.js

Now you define your Angular application and controllers using the combination of RequireJS and AngularJS syntax in the AngularApp.js file:

 define(['angularAMD', 'angular-route'], function (angularAMD) { var app = angular.module("webapp", ['ngRoute']); app.config(function ($routeProvider) { $routeProvider.when("/home", angularAMD.route({ templateUrl: 'views/home.html', controller: 'HomeCtrl', controllerUrl: 'ctrl/home' })) }); return angularAMD.bootstrap(app); }); define(['app'], function (app) { app.controller('HomeCtrl', function ($scope) { $scope.message = "Message from HomeCtrl"; }); }); 

Finally: your HTML page requests application links with a link to require.js and a data-main attribute indicating the application file.

 <script data-main="js/AngularMain" src=".../require.js"></script> 

Once again: the .js file extension is optional


+6
source

You can verify that jQuery has loaded correctly with the following code.

 if (typeof jQuery != 'undefined'){ // jQuery related code } 

You can determine if angular is loaded correctly using the following code,

 if(typeof angular != 'undefined') { // angular related code } 

Thus, there will be no conflict in the code, if jQuery exists, jQuery code will be launched. And if angular, then angular code will be launched.

You can use jQuery noconflict to ensure that $ does not conflict with any other library

 (function($){ // jQuery code here will not conflict with any other codes. })(jQuery); 

If you have multiple versions of angular, the following code will help you resolve conflicts. More details

 (function() { // Save a copy of the existing angular for later restoration var existingWindowDotAngular = window.angular; // create a new window.angular and a closure variable for // angular.js to load itself into var angular = (window.angular = {}); /* * Copy-paste angular.js and modules here. They will load themselves into * the window.angular object we just created (which is also aliased as * "angular") */ .. // notice this refers to the local angular variable declared above, not // window.angular angular.module('MyWidget', ['ngSanitize']); ... //Manually bootstrap so the old angular version doesn't encounter //ng-app='MyWidget' and blow up angular.element(document).ready(function() { angular.bootstrap(document.getElementById('my-widget', ['MyWidget']); // restore the old angular version window.angular = existingWindowDotAngular; }); }); 
+4
source

You can use the following function to add a custom script to the page,

 function loadScript(url, callback) { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url; script.onreadystatechange = callback; script.onload = callback; document.body.appendChild(script); } 

and for jQuery code you can try the following code

 var myCode = function () { var jQuery_your_version = $.noConflict(true); (function ($) { // your custom code will go inside this section $("#output").append("New code with version: " + $.fn.jquery + "<br/>"); }(jQuery_your_version)); $("#output").append("New code with version: " + $.fn.jquery + "<br/>"); }; if (typeof jQuery == 'undefined' || $.fn.jquery != "1.11.1") { loadScript("http://code.jquery.com/jquery-1.11.1.min.js", myCode); } else { myCode(); } $("#output").append("Old code with version: " + $.fn.jquery + "<br/>"); 

Demo

For angular code

 var myCode = function (ang, oldAngular) { $("#output").append("New custom code with version: " + ang.version.full + "<br/>"); window.angular = angular = oldAngular; // this is after your code and it is refering to the old angular $("#output").append("New code with version: " + angular.version.full + "<br/>"); }; if (typeof angular == 'undefined' || angular.version.full != "1.2.20") { var existingWindowDotAngular = window.angular; var angular = (window.angular = {}); loadScript("http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.20/angular.js", function () { myCode(angular, existingWindowDotAngular); }); } else { myCode(angular, angular); } 

Demo

EDIT

More information on angular for a better understanding,

var existingWindowDotAngular = window.angular; load the existing angular object into a variable var angular = (window.angular = {}); will reset the existing angular object.

The following loadScript() code loadScript() load the required version of angular and create a new angular object with the new version. then in the callback function we can do the necessary work. therefore, if you see Demo , you will see that the new version is displayed, then we reset window.angular to the old version using window.angular = angular = oldAngular; therefore, the old version is now displayed in Demo .

+4
source

Instant Call Function (IIFE) Expression

A generic template in JavaScript is a function that is called immediately by an expression. This template creates a function expression and then immediately executes that function. This template is extremely useful for cases where you want to avoid contaminating the global namespace with code - variables declared inside a function are not visible outside of it.

Source: http://stage.learn.jquery.com/javascript-101/functions/#immediately-invoked-function-expression-iife

$ Alias ​​protection and adding scope

The $ variable is very popular among JavaScript libraries, and if you use another library with jQuery, you will need to make jQuery do not use $ with jQuery.noConflict (). However, this will violate our plugin, as it is written with the assumption that $ is an alias of the jQuery function. To work well with other plugins and the alias jQuery $, we need to put all of our code inside. The function expression is called immediately, and then the jQuery function is passed and name the parameter $:

 (function ( $ ) { $.fn.greenify = function() { this.css( "color", "green" ); return this; }; $.ltrim = function( str ) { return str.replace( /^\s+/, "" ); }; $.rtrim = function( str ) { return str.replace( /\s+$/, "" ); }; }( jQuery )); 

source: http://learn.jquery.com/plugins/basic-plugin-creation/

When you look at the IIFE structure, you will see something like:

 (function($){})( jQuery )); 

The jQuery variable is the global object that you pass to the function, so the $ sign will always be the "clean" jQuery variable in the rest of your function. If I were you, I would study this template and use it in all your JavaScript to avoid conflicts. Of course, a site using your script (s) should include jQuery (or any other library you want to use).

To show you how this works, I created jsFiddle .


Update

I understand. You want to include your library yourself so you never have conflicts. When something sounds good to be true, usually it is. You are not the first to want this. The "problem" is called CORS . You cannot include anything from another (additional) domain without permission (it can be installed on the server side). This is really a security issue. I did my best to show you this in Fiddle .

+2
source

Using this noConflict() library, the function can easily restore everything after use.

The jquery part is simple: http://api.jquery.com/jquery.noconflict/

When you run this:

 jQuery.noConflict( true ); 

Jquery clears everything from the global namespace.

The situation of angular is less clear. There is a related traction request:

https://github.com/angular/angular.js/pull/8596

This means that you have to wait for them to combine this with stable, or you need to do it manually. In any case, this will restore the pre-angular state:

 angular.noConflict(); 

If you want to create one large file, it should be something similar:

  • Insert jquery source. or
  • Insert angular.js source (when using PR)
  • Do whatever you like with them.
  • And restore the original state using these two lines:

the code:

 jQuery.noConflict( true ); angular.noConflict(); 
+1
source

The approach described below should run on any web page that has javascript enabled. Library agnostic. No dependencies. Using an approach like jsonp .

Create a form element to configure Call-To-Action settings. Save the selected / created settings in the json object - or create without saving on the fly. Including a global identifier for a specific client and its own database.

Include the saved settings in IIFE , called a script on the client page, resulting in a jsonp call.

i for example

After collecting the settings in the form , saving to a json object completed by IIFE on the server / service may appear as

 (function() { var button = document.createElement("button"); // jsonObj.outerElem var link = document.createElement("a"); // jsonObj.innerElem link.href = "#"; // jsonObj.href link.innerText = "Call To Action!"; // jsonObj.label link.style.textDecoration = "none"; // jsonObj.styles button.appendChild(link); // order jsonObj elems for DOM display button.style.fontSize = "36px"; // jsonObj.styles return callback(button) // return jsonObj elems }()); 

the above file name will include a global identifier for the parameters stored in the json object for this client, for example, "cta-123.js", where 123 will be global [client-id] for the client and / or client, configured json object and / or callback functions.

On the client side, two script in the following order

 <script type="text/javascript"> // define global `callback` function // `cta` : `Call-To-Action` `button`, `form` , `element` , etc. callback = function(cta) { // do stuff with `cta` document.body.appendChild(cta) }; </script> <script type="text/javascript" src="https://cta-service/cta-[client-id].js"> 

The result in the Call to Action element is added to the client-defined element in the callback

jsfiddle http://jsfiddle.net/guest271314/rgokqyfp/

+1
source

The "namespace" of your code is closed and include only any libraries if they do not already exist on the page. The best way to do this would be this.

some_script.js

 (function(root) { function includeJQuery() { var s = root.document.createElement('script'); s.src = "//code.jquery.com/jquery-1.11.1.min.js"; root.document.getElementsByTagName('head')[0].appendChild(s); } function waitForJQuery() { if(root.jQuery === undefined || root.jQuery.fn.jquery !== "1.11.1") { root.setTimeout(waitForJQuery, 100); } else { var jQ = jQuery.noConflict(true); initMyApplication(jQ); } } if(root.jQuery === undefined || root.jQuery.fn.jquery !== "1.11.1") { includeJQuery(); waitForJQuery(); } else { initMyApplication(root.jQuery); } function initMyApplication(jQuery) { // // YOUR CODE HERE // } }(window)); 

Remember to change any occurrences of window in your code to root , and any functions you want to access globally should be root properties.

For example: if you want the createCtaModal() function to createCtaModal() called by the user, you must define it in the code as:

 root.createCtaModal = function() { ... } 

EDIT

Editing done so you can use a specific version of jQuery ...

script: http://jsfiddle.net/2rg7cq26/2/

+1
source

What about:

We use the fact that http://api.jquery.com/jquery.noconflict/ returns a reference to a jQuery function.

0
source

Source: https://habr.com/ru/post/1200441/


All Articles