Pass gtm id dynamically to gtm script in head section - reactjs

I have integrated google tag manager in my react js application but the problem is I have to pass the gtm id present in gtm script dynamically and turn on and off datalyer dynamically depending upon the response of the value coming from API.
I have created a component LoadAppKeys which receives a value on which I decide whether gtm is enabled or not. But how do I pass the gtm id dynamically to the script present in head section of index.html and append the script in head if value is 1 and not if its 0.
class LoadAppKeys extends React.PureComponent {
componentDidMount() {
this.props.getStorefrontConfigs();
}
componentWillReceiveProps(nextProps) {
if (!nextProps.loading) {
const gtm = getGTM(nextProps.storefrontConfig);
if (R.equals(gtm.gtm_enabled, 1)) {
var script = document.createElement('script');
script.type = "text/javascript";
script.text = myGTM(window, document, 'script', 'dataLayer', "GTM-KQZGSBW");
document.head.appendChild(script);
}
}
}
-------------------------------------
function myGTM(w, d, s, l, i) {
(function (w, d, s, l, i) {
w[l] = w[l] || []; w[l].push({
'gtm.start':
new Date().getTime(), event: 'gtm.js'
}); var f = d.getElementsByTagName(s)[0],
j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src =
'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', gtm_id);
}
Want to load the script everytime the page based upon the value in loadAppKeys component.

You can directly call myGTM, instead of doing the whole script insertion. Otherwise if you want to do the insertion all you need is determine the src attribute, example:
script src = 'https://www.googletagmanager.com/gtm.js?id='+id
In there you don't mention how you get the id, but basically change id with your variable.

Related

Is it possible to show gradients with react-svgmt?

I would like to use react-svgmt to manipulate SVG's. These SVG's can be uploaded from the users. My problem is, that if the SVG has a gradient these parts of the SVG are not shown.
Has anybody a solution for my problem to reactivate these links after the import of the SVG via react-svgmt?
With the developertools of my browser I was be able the see that the elements are in the code, but the grandients will be linked to the elements and these links are broken.
I have seen that other people has the same problem with gradients and created an issue on github, but the developer did not respond.
I found a solution for my problem.
react-svgmt add to elements like linearGradients "-{nr}" to its id-names. Then this fill:url(#linear-gradient-2); does not work anymore in the style-tags, because it must be fill:url(#linear-gradient-2-{nr});.
So the first SVGProxy after loading is <SvgProxy selector="linearGradient" onElementSelected={handleGradients} ></ SvgProxy>
an the function handleGradients looks like following and saves the {nr}
const handleGradients = (gradients) => { if (typeof gradients.length !== 'undefined') { const output = gradients.map((g, i) => { nr = g.id.substring(g.id.lastIndexOf("-")+1); setNr(g.id.substring(g.id.lastIndexOf("-")+1)); if(g.href.baseVal.length > 0) { var base = g.href.baseVal; g.href.baseVal = base + '-' + nr; } return g; }); } else { nr = gradients.id.substring(gradients.id.lastIndexOf("-")+1); setNr(gradients.id.substring(gradients.id.lastIndexOf("-")+1)); if(gradients.href.baseVal.length > 0) { var base = gradients.href.baseVal; gradients.href.baseVal = base + '-' + nr; } } };
Then I had another SVGProxy
<SvgProxy selector="defs > style" onElementSelected={handleStyleElem} ></ SvgProxy>
with the following handlefunction which replaces all urls with the schema from above
const handleStyleElem = (svgStyle) => { var styleStr = svgStyle.outerHTML; styleStr = styleStr.replaceAll(/url\(#((\w|-)*)\);/g, 'url(#$1-'+ nr +');'); svgStyle.outerHTML = styleStr; };

Webpack remove snippet code after build, how to keep it?

I defined a snippet code and show it in web so users can copy to use but after build app with Webpack production mode the snippet gone.
I think that webpack treat it like unused code so it be removed when build.
Snippet code:
let html = `
<script>
(function(w, d, t, s, n) {
...
const fn = function() {
(w[n].q = w[n].q || []).push(arguments);
};
w[n] = w[n] || fn;
const f = d.getElementsByTagName(t)[0];
const e = d.createElement(t);
const h = '?v' + new Date().getTime();
e.async = true;
e.src = s + h;
f.parentNode.insertBefore(e, f);
})(window, document, 'script', '${process.env.UNIVERSAL_SCRIPT}', 'fd');
window.fd('form', { userId: '${form.userId}', formId: '${form.id}' });
</script>
`;
html = jsBeautify.html(html, { indent_size: 2 });
Render in react component:
<SyntaxHighlighter language="xml" style={monokai} id="html">
{html}
</SyntaxHighlighter>
Here is demo repository: https://github.com/minhtranite/webpack-remove-snippet. Please run start and start:prod to see the difference result.
It looks like you haven't defined the variable form as a result of which the build is failing. Or, language="html" is causing it to be parsed as html. language="text" will render it as text.

How to pass php response data from one page to another page in angularjs without using localstorage

i have one doubt how can i pass data from one page to another page in angularjs without using localstorage and data should exist even if user reload that page.
Is there any way out from here or not?
Thank's in advance
you can use cookie's :
https://docs.angularjs.org/api/ngCookies/service/$cookies
you can refer to this JSbin link for example:
http://jsbin.com/duxaqa/2/edit
Also, there is a nice stackoverflow answer that match your needs i think, with a more complete explanation than mine:
How to access cookies in AngularJS?
You can put data to cookie
// set cookie on one page:
setCookie("key", value);
// get cookie on another page:
var val = getCookie("key");
Using functions:
function setCookie(name, value, options) {
options = options || {};
var expires = options.expires;
if (typeof expires == "number" && expires) {
var d = new Date();
d.setTime(d.getTime() + expires * 1000);
expires = options.expires = d;
}
if (expires && expires.toUTCString) {
options.expires = expires.toUTCString();
}
value = encodeURIComponent(value);
var updatedCookie = name + "=" + value;
for (var propName in options) {
updatedCookie += "; " + propName;
var propValue = options[propName];
if (propValue !== true) {
updatedCookie += "=" + propValue;
}
}
document.cookie = updatedCookie;
}
function getCookie(name) {
var matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
));
return matches ? decodeURIComponent(matches[1]) : undefined;
}
But keep in mind that cookies size limited: 4093 bytes per domain.
you can pass data to another page using $rootScope or $cookieStore. But, only $cookieStore will save data when user reload the page. Take a look how to implement example:
angular.module('cookieStoreExample')
.controller('ExampleController', function($cookieStore) {
// Put cookie
$cookieStore.put('myFavorite','oatmeal');
// Get cookie
var favoriteCookie = $cookieStore.get('myFavorite');
// Removing a cookie
$cookieStore.remove('myFavorite');
});

IndexedDB key generator resets after put-transaction

This problem has me stumped.
For some reason, the autoincrementing key generator in indexedDB resets after performing and update on an existing object with a put-transaction, leading to overwrites of data in the database.
For my app, I'm using a self written IndexedDB service for angularJS with all the basic CRUD functions implemented.
I may also add that I'm developing with Ionic Framework, even though I doubt that is to blame.
Considering the service is a work-in-progress, I've let the key path for an object store default to "id" with an autoincrementing strategy.
The indices for the given store, nevertheless, are up to the user to decide in a specific object.
As an example:
dbHelper.objectStores = [{'employees',
indices: [{indexName: 'name', isUnique: false},
{indexName: 'phone', isUnique: true}]}];
This would, unless already created in the db, create the object store 'employees' with indices 'name' and 'phone', where 'phone' would have to be a unique value while 'name' would not.
Here is the implementation of the openDB function.
Please note that dbHelper.objectStores is supposed to be empty as it's up to the user to assign these properties before opening the db(or else it is defaulted).
angular.module('dbProvider', [])
.factory('$db', ['$window', function($window) {
// DB Object
var dbHelper = {};
// Properties - Are given defaults unless assigned manually by user before openDB is invoked.
dbHelper.dbName = 'defaultDB';
dbHelper.dbVersion = 1;
dbHelper.objectStores = [];
dbHelper.openDB = function(onCompleteCallback, onErrorCallback) {
console.log('Atempting to open db with name ' + dbHelper.dbName + '.');
var request = $window.indexedDB.open(dbHelper.dbName, dbHelper.dbVersion);
// Invoked by indexedDB if version changes
request.onupgradeneeded = function(e) {
console.log('Version change. Current version: ' + dbHelper.dbVersion);
var db = e.target.result;
e.target.transaction.onerror = onErrorCallback;
if(dbHelper.objectStores.length === 0) {
dbHelper.objectStores.push({name:'defaultStore', indices: []});
}
for(var store in dbHelper.objectStores) {
if(db.objectStoreNames.contains(dbHelper.objectStores[store].name)) {
console.log(dbHelper.objectStores[store].name + ' deleted.');
db.deleteObjectStore(dbHelper.objectStores[store].name);
}
var newStore = db.createObjectStore(dbHelper.objectStores[store].name, {keyPath: "id", autoIncrement: true});
for(var index in dbHelper.objectStores[store].indices) {
newStore.createIndex(dbHelper.objectStores[store].indices[index].indexName,
dbHelper.objectStores[store].indices[index].indexName,
{unique : dbHelper.objectStores[store].indices[index].isUnique});
}
console.log(dbHelper.objectStores[store].name + ' created.');
}
};
request.onsuccess = function(e) {
console.log('DB ' + dbHelper.dbName + ' open.');
dbHelper.indexedDB.db = e.target.result;
onCompleteCallback();
};
request.onerror = onErrorCallback;
};
Here are some of the CRUD functions(the ones in question):
dbHelper.findItemWithIndex = function(keyValue, storename,
onCompleteCallback,onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var index = store.index(keyValue.key);
index.get(keyValue.value).onsuccess = function(event) {
onCompleteCallback(event.target.result);
};
};
dbHelper.addItemToStore = function(item, storename,
onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.add(item);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
dbHelper.deleteItemFromStore = function(itemId, storename,
onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.delete(itemId);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
dbHelper.updateItem = function(item, storename, onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.put(item);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
Finally, the code from the controller where the transactions are invoked.
The strategy here, is that the item is added to the db using the addItemToStore function the first time it is persisted, and then afterwards the updateItem function.
After adding the first time, the object is immediately fetched in order to keep working on it with the assigned id from the db.
$scope.updateTemplate = function() {
console.log('Saving..');
var onCompleteCallback = {};
if(!$scope.formTemplate.firstSave) {
onCompleteCallback = $scope.updateModel;
} else {
$scope.formTemplate.firstSave = false;
onCompleteCallback = $scope.setId;
}
$db.updateItem($scope.formTemplate, $scope.objectStore.name,
onCompleteCallback, $scope.dbError);
};
$scope.newItem = function() {
$db.addItemToStore($scope.formTemplate, $scope.objectStore.name,
$scope.setId, $scope.dbError);
};
$scope.setId = function() {
$db.findItemWithIndex(
{key: 'title',
value: $scope.formTemplate.title},
$scope.objectStore.name,
function(result) {
console.log(JSON.stringify(result));
$scope.formTemplate = result;
},
function(error) {
$scope.dbError(error);
});
}
It's here everything goes to hell.
I add an object, go back to another view and find it in the list with id=1.
I add another object, go back to the list view, and there it is with id=2.
And so forth and so forth..
Then, after updating either of the objects with the $scope.updateTemplate function, which also works like a charm, things get interesting:
The next object added gets id=1 and totally erases good old numero uno from earlier.
The next objects also get id's that cause them to replace the already existing objects.
What could cause this?
For testing I'm using Safari 8 in OS 10.10 and I'm deploying to an LGG2 with KitKat 4.4.2.
To be honest, I skimmed, but I saw this, "Safari 8" - the latest iOS and Safari have serious bugs with IndexedDB: http://www.raymondcamden.com/2014/9/25/IndexedDB-on-iOS-8--Broken-Bad
In iOS9, many of the IndexedDb bugs are fixed, but not all. We are currently testing on iOS9 Beta 2 and this particular bug that you found is not fixed.
We were able to work around this problem by not using autoincrement on our object stores. We just manually find the max key value and increment that.
Inserting an object looks something like this:
var store = db.transaction([entity], "readwrite").objectStore(entity);
store.openCursor(null, "prev").onsuccess = function (event) {
var maxKey = event.target.result.key || 0;
object.id = maxKey + 1;
store.add(object);
}

Userscript breaking pages outside of domain

Even though I have my userscript restricted to one domain, any site I visit that uses Jquery experiences all kinds of nasty issues when my script is active. Checking the error console in chrome reveals an identical error on all sites:
"Uncaught TypeError: Property '$' of object [object Window]"
What's causing this? My objective is to get my userscript running in noconflict mode on a site that uses both jquery and prototype. I didn't make the code above var = myFunction, so I don't know what about it is causing the problem I'm running into. Any suggestions?
// ==UserScript==
// #name Restore Dashboard Tags
// #namespace http://userstyles.org
// #description This script restores a user's tracked tag list to the sidebar on tumblr
// #author
// #homepage
// #history 1.0 first version
// #include http://www.tumblr.com/*
// #match http://www.tumblr.com/*
// ==/UserScript==
var jQuery, $ = null;
function addJQuery(callback) {
var p = null;
if(window.opera || window.navigator.vendor.match(/Google/)) {
var div = document.createElement("div");
div.setAttribute("onclick", "return window;");
p = div.onclick();
}
else {
p = Window;
}
jQuery = $ = p.jQuery.noConflict();
callback();
}
var myFunction = function() {
jQuery('div#right_column ul:first-child').after('<ul class="controls_section" id="tracked_tags"></ul>');
jQuery('div.tracked_tags a').each(function (i) {
var tagID = jQuery(this).attr("id");
var tagIDNumber = tagID.replace('tag_','');
var tagName = jQuery(this).attr("href");
var tagNameClean = tagName.replace('/tagged/','');
var tagContent ='';
tagContent += '<li><a href="'+tagName+'" id="'+tagID+'" class="tag">';
tagContent += '<div class="hide_overflow">'+tagNameClean+'</div>';
tagContent += '<span id="tag_unread_'+tagIDNumber+'" class="count" style=""></span></a></li>';
jQuery(tagContent).appendTo('div#right_column ul#tracked_tags');
});
};
var NewPosts = function(){
jQuery('div.tracked_tags > div').each(function (i) {
var thisIndex = jQuery(this).index();
if (jQuery(this).find('small').length){
var postCount = jQuery(this).find('small').text();
jQuery('div#right_column ul#tracked_tags li:eq('+thisIndex+')').find('.count').html(postCount.replace("new posts", "") );
}
});
setTimeout(NewPosts,30000);
}
addJQuery(myFunction);
addJQuery(NewPosts);
The problem has been solved! Someone on another site IDed the culprit as jQuery = $ = p.jQuery.noConflict();; since I wasn't loading my own copy of Jquery I didn't need noConflict, and its usage was hiding Jquery from the rest of the page.

Resources