Adding Segment telemtry to React component that is only one DOM node - reactjs

I'm looking to add segment analytics to my JupyterLab extension. No worries if you've never heard of a JupyterLab extension - the best way to think about it: I get control over a single node in the DOM where I can place some HTML, so I'm doing the following:
function Welcome(props) {return <h1>Hello</h1>;}
ReactDOM.render(<Welcome/>, dom_element_i_control)
This all works fine - I'm now looking to add some analytics code to this. For example, I'd like to be able to:
See when my code is rendered
See when someone interacts with my rendered element (e.g. if there was a button in the Welcome function, when the user clicked on it).
However, segment is a JS library that is delivered as a script that you load into a webpage at the top in a string tag like:
<script>
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&...}}();
</script>
Where would I even put this code? I don't have control over the larger page + HTML, so I'm not sure where I can slap this so I can start using analytics.
Thanks for any information!

My workaround:
Instead of using the above linked segment script, I used the analytics-node package from segment.
I create an Analytics object right before ReactDOM.render - and then can use it wherever I want :)
Note that this will not work for anyone who uses an add blocker, obviously!

Related

Can I download an image if it's in base64 format?

I'm developing a React App, and I have a backend in NodeJS.
In my Mongo Schema I have an array that stores multiple strings, these strings are some images.
I saved them as base64. Now I want to display them in my app, works perfectly fine with src from img tag, but I want to create a button that allows the user to download those pictures, is there any solution to this? Can I convert back that string and make it downloadable? Thank you very much for you time, I'm waiting for your ideas!
Note: The examples in the snippets will not work live because Stack Overflow sandboxes snippets without allow-downloads, but they should work on your page.
Depending on your exact use case, you have different options. The easiest one would be using an <a> tag with the download attribute instead of a button, like this:
<a download="myImage.gif" href="data:image/gif;base64,R0lGODdhEAAQAMwAAPj7+FmhUYjNfGuxYYDJdYTIeanOpT+DOTuANXi/bGOrWj6CONzv2sPjv2CmV1unU4zPgISg6DJnJ3ImTh8Mtbs00aNP1CZSGy0YqLEn47RgXW8amasW7XWsmmvX2iuXiwAAAAAEAAQAAAFVyAgjmRpnihqGCkpDQPbGkNUOFk6DZqgHCNGg2T4QAQBoIiRSAwBE4VA4FACKgkB5NGReASFZEmxsQ0whPDi9BiACYQAInXhwOUtgCUQoORFCGt/g4QAIQA7">Download GIF</a>
If you need to keep using a button and you want to trigger the download programmatically, you can create an <a> tag (without displaying it) and trigger a click:
const a = document.createElement('a')
a.download = 'myImage.gif'
a.href = 'data:image/gif;base64,R0lGODdhEAAQAMwAAPj7+FmhUYjNfGuxYYDJdYTIeanOpT+DOTuANXi/bGOrWj6CONzv2sPjv2CmV1unU4zPgISg6DJnJ3ImTh8Mtbs00aNP1CZSGy0YqLEn47RgXW8amasW7XWsmmvX2iuXiwAAAAAEAAQAAAFVyAgjmRpnihqGCkpDQPbGkNUOFk6DZqgHCNGg2T4QAQBoIiRSAwBE4VA4FACKgkB5NGReASFZEmxsQ0whPDi9BiACYQAInXhwOUtgCUQoORFCGt/g4QAIQA7'
a.click()
(If you need to support older browsers, you may have to temporarily insert the tag into the DOM and trigger the click in a setTimeout(..., 0).)
You can also use object URLs like it's shown here but it's probably easier to go the data URI route since you already have such a URI.

Replace HTML block by another one with Angular JS

I am trying to build an Angular JS app where a certain block of HTML is replaced by another one (both are input forms) and they should both be in the same location.
I have used ng-show/hide and it works with regards to the hiding/showing. The only problem is that the second peace of html doesn't appear on the same location as where the previous one was located but next to it (feels like the second one is still "there" but invisible.
Is there another way of doing this or does this work for anyone else?

Scrolling website with angular: states/routing setup

I can't seem to wrap my head around a routing setup for a project I'm working on at the moment. I tried ngRoute, angular-sement-router, now trying ui-router, however I'm still struggling to understand how to use them in my scenario.
I've attached an image to illustrate the kind of a thing I want to achieve. Basically, I need to have two types of pages — one type is a multi-section scrolling page. Another one is just a plain page with text and images.
The multi-section one should scroll to a certain section according to a current route. Each section has a set of subsections. So the route like
#!/section-2/subsection-2
should make the app scroll to Section-2 (smooth scrolling is not an issue at the moment) and activate Subsection 2.
I tried using named ui-views, but then I have to have an initial state of each named ui-view on my route state. It leads to another problem. If let's say I would navigate to
#!/section-1/subsection-1
my Section 1 subsection will return to whatever is set in the initial state.
Another issue is that my setup should separate Sections 1-4 from Section 5 which is a separate page.
I hope my description makes sense. Would love to here any advice on what I can read or where can I find some useful ideas. Thanks in advance.

adding controller later

I'm trying to create an NG app where parts can be enabled/disabled dynamically. The idea is to have an "admin" page, where parts of the app can be enabled or disabled, and then see new functionality appear, in the form of an adjusted menu at the top of the page, and matching routes, controllers, etc loaded into the app (I'm using SocketStream w/ NG).
The first step was to add / remove routes dynamically, for which I found a solution at https://stackoverflow.com/a/13173667 - working well, as far as I can tell.
Next, adding items to the menu bar - easy with ng-repeat on ul/li items.
So the app adjusts its menu and recognizes the corresponding route. So far so good.
The problem comes with registering a controller. I'm calling myApp.controller('SandboxCtrl',[...]) with proper args (same as what worked when initialising statically on startup), but the controller does not appear to get loaded or inited properly. Navigating to the newly added route generates errors such as:
Error: Argument 'SandboxCtrl' is not a function, got undefined
assertArg#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:973
assertArgFn#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:984
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:4638
update#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:14007
$broadcast#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:8098
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7258
wrappedCallback#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6658
wrappedCallback#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6658
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:6695
$eval#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7848
$digest#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7713
$apply#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:7934
#http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.js:5433
I'm currently at a loss on how to proceed. I've not been able to find a solution on the web. The app is too large to put in a jsFiddle, but I can commit the last changes on GitHub if needed.
Questions: is this feasible? what can I do to debug this? any examples I could look at?
EDIT: The code is now at https://github.com/jcw/housemon (needs node/npm/redis). It's easy to reproduce the problem: launch with "npm start", browse to localhost:3333, go to admin tab, click on "jcw-sandbox" and then "Install". Top menu will update with new a "Sandbox" entry. Clicking on that entry generates the error shown above.
Oh, almost forgot: relevant code is in client/code/app/main.coffee and client/code/modules/routes.coffee ...
The answer turns out to be two-fold:
the NG calls were made from SocketStream RPC callbacks, and had to be wrapped in $scope.$apply calls - my bad, didn't know about this SS/NG interaction
the rest of the solution was outlined by #matys84pl - pick up $controllerProvider (and $filterProvider) early on, so they can be called at a later time instead of the normal "app.controller" and "app.filter" members, which don't seem to work anymore later on
Example code in GitHub, I'll link to a specific commit so this answer stays valid:
https://github.com/jcw/housemon/commit/f199ff70e3000dbf57836f0cbcbb3306c31279de

module block view only prints if it is on a certain page

In Drupal 7 Is there a way for me to insert my block into a region only on certain pages inside of a module code? Or do I have to do that in the gui block list?
I've created a banner module, but want to be able to give the ability to choose the pages it appears on. For starts, it could appear only on the front page. I tried a $is_front check, but I am getting an error that $is_front or $variables are undefined.
This doens't work inside of my block_view() function in my module.
if ($is_front){
$block['content'] = theme('mydata', $banner_node_list);
}
I think your best bet is to use the block GUI to select where it appears. I can't see any benefits to doing it in the code when it's already built in to be honest.

Resources