Tutorials on Using Mixpanel in an MVC app - model-view-controller

I am using content security policy in a web app and so the MixPanel JavaScript library that using inline script sadly just won't work for me. Before I invest time figuring out how to use the Java Lib I wonder if anyone has done it and has a tutorial they can point me to or advice / examples? Google is sadly not my friend tonight....

Following should solve the problem as long as browser support async javascript load. [I have tested it with only Mixpanel 2.2]
<script type="text/javascript">
var b = window.mixpanel || [];
if (!b.__SV) {
var i, g;
window.mixpanel = b;
b._i = [];
b.init = function (a, e, d) {
function f(b, h) {
var a = h.split(".");
2 == a.length && (b = b[a[0]], h = a[1]);
b[h] = function () {
b.push([h].concat(Array.prototype.slice.call(arguments, 0)))
}
}
var c = b;
"undefined" !==
typeof d ? c = b[d] = [] : d = "mixpanel";
c.people = c.people || [];
c.toString = function (b) {
var a = "mixpanel";
"mixpanel" !== d && (a += "." + d);
b || (a += " (stub)");
return a
};
c.people.toString = function () {
return c.toString(1) + ".people (stub)"
};
i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");
for (g = 0; g < i.length; g++)
f(c, i[g]);
b._i.push([a, e, d])
};
b.__SV = 1.2
}
b.init("YOUR TOKEN");
</script>
<script type="text/javascript" src="http://cdn.mxpnl.com/libs/mixpanel-2.2.min.js" async="true"></script>
replace "YOUR TOKEN" with your mixpanel toekn.

Related

How to copy a formula from "Parent Tab" to "Child Tab" on Google Sheet

I'm doing RolePlay Character Sheets on a "Parent tab" I've called "MODEL", where I masterize my formulas.
I've created a second tab "Character1" and a third one "Character2". But when I try to use =QUERY or =TEXTFORMULA or whatever. It doesn't make the formulas to calculate on the actual spreadsheet, it just get the data from the "MODEL" tab.
My only way is actually to copy/past all my formulas, but if I do a mistake, I'll have to correct it in every spreadsheet every time.
Is that possible to have a formula which take the cell at:
MODELE!AE58
And automatically generate the same formulas in every tabs:
CHARACTER1!AE58
CHARACTER2!AE58
etc...
Sorry if its blur, I'm doing my best to explain.
simple
Try
function onEdit(e) {
var sh = e.source.getActiveSheet()
var rng = e.source.getActiveRange()
if (rng.getFormula() != '' && sh.getName() == 'MODEL') {
var excl = ['MODEL', 'OTHER'];//excluded sheets
SpreadsheetApp.getActiveSpreadsheet().getSheets().forEach(sh => {
if (!~excl.indexOf(sh.getSheetName())) {
sh.getRange(rng.getA1Notation()).setFormula(rng.getFormula())
}
})
}
}
when you change a formula in MODEL, this will also change in other tabs excepts excluded ones
multiple
If you edit the formulas by dragging them into the MODEL sheet, use this one which allows you to edit all the formulas at once
function onEdit(e) {
var sh = e.source.getActiveSheet()
if (sh.getName() != 'MODEL') return;
for (var i = e.range.rowStart; i <= e.range.rowEnd; i++) {
for (var j = e.range.columnStart; j <= e.range.columnEnd; j++) {
if (sh.getRange(i, j).getFormula() != '') {
var excl = ['MODEL', 'OTHER'];//excluded sheets
SpreadsheetApp.getActiveSpreadsheet().getSheets().forEach(child => {
if (!~excl.indexOf(child.getSheetName())) {
child.getRange(sh.getRange(i, j).getA1Notation()).setFormula(sh.getRange(i, j).getFormula())
}
})
}
}
}
}
global
Il you need to reset all formulas, enable google sheets api and try
function onOpen() {
SpreadsheetApp.getUi().createMenu('⇩ M E N U ⇩')
.addItem('👉 Apply all formulas from MODEL to all tabs', 'spreadFormulas')
.addToUi();
}
function spreadFormulas() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('MODEL')
if (sh.getName() != 'MODEL') return;
var data = [];
var formulas = sh.getRange(1, 1, sh.getLastRow(), sh.getLastColumn()).getFormulas()
for (var i = 0; i < formulas.length; i++) {
for (var j = 0; j < formulas[0].length; j++) {
if (formulas[i][j] != '') {
var excl = ['MODEL', 'OTHER'];//excluded sheets
SpreadsheetApp.getActiveSpreadsheet().getSheets().forEach(child => {
if (!~excl.indexOf(child.getSheetName())) {
data.push({
range: `${child.getName()}!${columnToLetter(+j + 1) + (+i + 1)}`,
values: [[`${formulas[i][j]}`]],
})
}
})
}
}
}
if (data.length) {
var resource = {
valueInputOption: 'USER_ENTERED',
data: data,
};
try { Sheets.Spreadsheets.Values.batchUpdate(resource, ss.getId()); } catch (e) { console.log(JSON.stringify(e)) }
}
}
function columnToLetter(column) {
var temp, letter = '';
while (column > 0) {
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
}
if your sheet is called MODELE try on some other sheet just:
=MODELE!AE58
for array it would be:
={MODELE!AE58:AE100}
also take a look into "Named Ranges" - maybe you will find it more handy

{d3.js} migration v3 to v4: code work on v3 (d3.layout.stack()) error v4 (d3.stack())

I'm trying to migrate D3 from v3 to v4:
Read:
https://github.com/d3/d3/blob/master/CHANGES.md#shapes-d3-shape
See:
d3.layout.stack ↦ d3.stack
I changed my working code:
Code working on v3: (d3.layout.stack())
Code producing error in v4: (d3.stack())
V4:
var dvstack = d3.stack();
var layers = dvstack(d3.range(nLocal).map(function(d,i) { ...
console.log(dvstack);
function stack(data) {
var kz = keys.apply(this, arguments),
i,
m = data.length,
n = kz.length,
sz = new Array(n),
oz;
for (i = 0; i < n; ++i) {
for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m;++j) {
si[j] = sij = [0, +value(data[j], ki, j, data)];
sij.data = data[j];
}
si.key = ki;
}
for (i = 0, oz = order(sz); i < n; ++i) {
sz[oz[i]].index = i;
}
offset(sz, oz);
return sz; }
layers[c].dvnum = c;
Error:
SCRIPT5007: Unable to set property 'dvnum' of undefined or null reference
V3:
var stack = d3.layout.stack();
var layers = stack(d3.range(nLocal).map(function(d,i) { ...
console.log(stack);
function stack(data, index) {
if (!(n = data.length)) return data;
var series = data.map(function(d, i) {
return values.call(stack, d, i);
});
var points = series.map(function(d) {
return d.map(function(v, i) {
return [ x.call(stack, v, i), y.call(stack, v, i) ];
});
});
var orders = order.call(stack, points, index);
series = d3.permute(series, orders);
points = d3.permute(points, orders);
var offsets = offset.call(stack, points, index);
var m = series[0].length, n, i, j, o;
for (j = 0; j < m; ++j) {
out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
for (i = 1; i < n; ++i) {
out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
}
}
return data; }
layers[c].dvnum = c;
Screenshot of the working code in v3:
Screenshot of the working code (D3 v3) console.log(layers)
Screenshot of the (D3 v4) console.log(layers)
Turns out, it's actually quite easy.
You simply want to transpose your matrix so that it's looks like somethings which is close to the array of objects the new stack function is waiting for:
var n = 4, // number of layers
m = 58, // number of samples per layer
stack = d3.stack().keys([0,1,2,3]);
stack.value(function (d, key) {
return d[key].y;
});
var layers = stack(d3.transpose(d3.range(n).map(function() { return bumpLayer(m, .1); }))),
Then it's a simple matter of modifying the names according to the new syntax.
I updated your fiddle so that it works for v4.
see:
https://jsfiddle.net/9y2g65qc/20/

What is d3.geo.pipeline?

If you follow Mike Bostock's bl.ocks, you know for the last 8 months d3.geo.pipeline() has been a frequent component to his projects.
But what's it do?
You see him set pipelines up like this:
var sketch = d3.geo.pipeline()
.source(d3.geo.jsonSource)
.pipe(resample, .020)
.pipe(jitter, .004)
.pipe(smooth, .005)
.sink(d3.geo.jsonSink);
via
There is no documentation in the d3.geo wiki.
Some beautified JS in the unreleased D3 used in the code example reveals this function:
lo.geo.pipeline = function() {
var n = [];
return {
source: function() {
return n[0] = arguments, this
},
pipe: function() {
return n.push(arguments), this
},
sink: function() {
for (var t, e = arguments[0].apply(null, [].slice.call(arguments, 1)), r = e; t = n.pop();) {
var u = [].slice.call(t, 1);
u.push(e), e = t[0].apply(null, u)
}
return function() {
return e.apply(this, arguments), r.value && r.value()
}
}
}
It also appears in these bl.ocks:
Back-facing Hemisphere
Multiple rotations
Satellite
I'm not familiar with d3.js, but I looked at its source code and found that this feature is located in branch graphics-pipeline.
For example you can find related code here: https://github.com/mbostock/d3/commit/a3f2adab7f85e2a0c82288ead88c1e484c9e3ea3
Small code snippet to illustrate how it works:
var pipeline = function () {
var pipes = [];
return {
source: function () {
pipes[0] = arguments;
return this;
},
pipe: function () {
pipes.push(arguments);
return this;
},
sink: function () {
var sink = arguments[0].apply(null, [].slice.call(arguments, 1)),
pipe;
while (pipe = pipes.pop()) {
var args = [].slice.call(pipe, 1);
args.push(sink);
sink = pipe[0].apply(null, args);
}
return sink;
}
};
};
var log = document.getElementById('log');
function f() {
var argsAsString = Array.prototype.join.call(arguments, ', ');
var resultName = 'r' + f.callCounter++;
log.innerHTML += resultName + ' = f(' + argsAsString + ')<br>';
return resultName;
}
f.callCounter = 1;
pipeline().
source(f, 'a', 1).
pipe(f, 'b', 2).
pipe(f, 'c', 3).
sink(f, 'd', 4);
<div id="log"></div>
Few comments about this feature:
Methods source and pipe work with the same private property pipes. The difference only is that source set initial value for pipes (pipes[0]), when each call to pipe pushes new pipe into collection.
Previous fact gives us knowledge about d3.geo.jsonSource internal structure. It should be similar to arguments passed to pipe: first argument is something callable (function), rest of arguments - parameters.
Assume that arguments = [f, a, b, c]. Then JavaScript pattern arguments[0].apply(null, [].slice.call(arguments, 1)) means: f(a, b, c). You can see several places of its usage in sink implementation.
Regarding practical usage.
We can use it if we need to "chain" (or "pipe") data processing. For example if we have such code:
function f(a, b, previousResult)
{
return a * b + (previousResult || 0);
}
var p = pipeline().
source(f, 1, 1).
pipe(f, 2, 10).
pipe(f, 3, 100).
sink(f, 4, 1000);
Then the result (value of p) will be 4321.
In this particular case we need to clarify what is d3.geo.jsonSink and d3.geo.jsonSource, but I hope that I helped you to see the meaning of pipeline function.

Sorting a treeStore in extJs messing up with the application

I have a treeStore ('planScreenStore') which I'm accessing in the following way :
updateStore : function() {
rootNodeID = globals.GlobalModel.planList.scope._id;
var planScreenStoreRootNode = this.planScreenStore.getRootNode();
if (!(planScreenStoreRootNode === undefined)) {
planScreenStoreRootNode.removeAll();
}
if (globals.GlobalModel.planList.children.length > 0) {
planScreenStoreRootNode.appendChild(
globals.GlobalModel.planList.children);
globals.GlobalModel.planList.children = planScreenStoreRootNode;
globals.GlobalModel.planListForCreateNewPlan = planScreenStoreRootNode;
}
I have to sort the treeStore on the basis of its field 'text'.
I have been able to do so in the following two ways:
updateStore : function() {
debugger;
rootNodeID = globals.GlobalModel.planList.scope._id;
var planScreenStoreRootNode = this.planScreenStore.getRootNode();
if (!(planScreenStoreRootNode === undefined)) {
planScreenStoreRootNode.removeAll();
}
if (globals.GlobalModel.planList.children.length > 0) {
planScreenStoreRootNode.appendChild(
globals.GlobalModel.planList.children);
globals.GlobalModel.planList.children = planScreenStoreRootNode;
globals.GlobalModel.planListForCreateNewPlan = planScreenStoreRootNode;
}
this.planScreenStore.sort('text','ASC');
and the other one:
updateStore : function() {
debugger;
rootNodeID = globals.GlobalModel.planList.scope._id;
var planScreenStoreRootNode = this.planScreenStore.getRootNode();
if (!(planScreenStoreRootNode === undefined)) {
planScreenStoreRootNode.removeAll();
}
if (globals.GlobalModel.planList.children.length > 0) {
planScreenStoreRootNode.appendChild(
globals.GlobalModel.planList.children);
globals.GlobalModel.planList.children = planScreenStoreRootNode;
globals.GlobalModel.planListForCreateNewPlan = planScreenStoreRootNode;
}
planScreenStoreRootNode.sort(function(n1, n2) {
debugger ;
var v1 = n1.data['text'].toUpperCase();
var v2 = n2.data['text'].toUpperCase();
if (v1 < v2)
return -1;
else if (v1 > v2)
return 1;
return 0;
});
I get the desired result with both the methods but somehow in both the cases, my application crashes after the sorting is performed while it works entirely fine without either of the sorting applied. Is it something related to how I'm accessing the NodeInterface (planScreenRootNode). How can i resolve this?

'JSON' is undefined error in IE only

I'm making an AJAX call to a WCF service and when I pass in my data i use JSON.stringify()
The call returns and works fine in FF, & Chrome, but not IE8. I get an error: 'JSON' is undefined
suggestions?
p.s. I also want this to work in IE7
Use json2 for a consistent cross browser implementation.
https://github.com/douglascrockford/JSON-js
I had the issue with IE9. IE9 was rendering my page in "quirks" mode, the solution was simply to add <!DOCTYPE html>. This took me out of "quirks" mode which I'm sure fixed more than just this issue!
Update
Check the JSON3 library. It works like a charm.
Changes from JSON2
I hope this helps.
Hope this helps. I got this from a few online sources long back. don't have their links. Sorry that i'm unable to cite references.
var JSON = JSON || {};
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function(obj) {
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string")
obj = '"' + obj + '"';
return String(obj);
} else {
// recurse array or object
var n, v, json = [], arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n];
t = typeof (v);
if (t == "string")
v = '"' + v + '"';
else if (t == "object" && v !== null)
v = JSON.stringify(v);
json.push((arr ? "" : '"' + n + '":') + String(v));
}
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
};
// implement JSON.parse de-serialization
JSON.parse = JSON.parse || function() {
var r = "(?:-?\\b(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b)", k = '(?:[^\\0-\\x08\\x0a-\\x1f"\\\\]|\\\\(?:["/\\\\bfnrt]|u[0-9A-Fa-f]{4}))';
k = '(?:"' + k + '*")';
var s = new RegExp(
"(?:false|true|null|[\\{\\}\\[\\]]|" + r + "|" + k + ")", "g"), t = new RegExp(
"\\\\(?:([^u])|u(.{4}))", "g"), u = {
'"' : '"',
"/" : "/",
"\\" : "\\",
b : "\u0008",
f : "\u000c",
n : "\n",
r : "\r",
t : "\t"
};
function v(h, j, e) {
return j ? u[j] : String.fromCharCode(parseInt(e, 16));
}
var w = new String(""), x = Object.hasOwnProperty;
return function(h, j) {
h = h.match(s);
var e, c = h[0], l = false;
if ("{" === c)
e = {};
else if ("[" === c)
e = [];
else {
e = [];
l = true;
}
for ( var b, d = [ e ], m = 1 - l, y = h.length; m = 0;)
delete f[i[g]];
}
return j.call(n, o, f);
};
e = p({
"" : e
}, "");
}
return e;
};
}();
To make your function works better in IE import JSON2 parser code in your file, as IE by default does not support JSON.Stringify().
It can be found here
In IE open the compatibility view settings and remove the localhost from the listbox for "Websites you have added to Compatibility View".
It worked for me.
JQuery 2.x is no longer compatible with IE 6-8. JQuery 2.0 beta 2 release notes
I know the main question is in regard to older versions of JQuery, but this was causing the error for me. I installed JQuery 1.x, which is API-compatible with JQuery 2.x, and added the following detection code:
<!--[if lt IE 9]>
<script src="js/jquery-1.11.1.min.js"></script>
<![endif]-->
<!--[if gte IE 9]>
<script src="js/jquery.min.js"></script>
<![endif]-->

Resources