Facebook "message us" button in polymer webapp - polymer

I want to add "message us" button to my Web app made on Polymer 3.
On Facebook site I found information that I have to add the Facebook SDK script in html body:
<script>
window.fbAsyncInit = function() {
FB.init({
appId : 'your-app-id',
autoLogAppEvents : true,
xfbml : true,
version : 'v3.0'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "https://connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
Then add div to my page where I want to add the button:
<div class="fb-messengermessageus"
messenger_app_id="<APP_ID>"
page_id="<PAGE_ID>"
color="<blue | white>"
size="<standard | large | xlarge>">
</div>
But in Polymer when I add this code to the page nothing happens.
Should I create a special polymer element or I am doing something wrong?
Any advice will be helpful
Thanks

This is not related to Polymer. You currently have an invalid chunk of HTML. As you can see in the div, they have several attributes which you need to input or select a value. For example, if your app id is 123456 and your page id is abcd, then you want it to be blue and large:
<div class="fb-messengermessageus"
messenger_app_id="123456"
page_id="abcd"
color="blue>"
size="large">
</div>
I can see the class fb-messengermessageus. Do they provide any styling CSS as well?

After days of studying, I found the solution. As Binh Bui said the problem is in the Shadow DOM. It's isolated from DOM and facebook SDK is not working in the web component. To bypass this and add facebook button to your web component we need to use "slots", more details here. But in my example I have two levels of shadow dom, so I need to make multi-level slot from index.html (DOM) file, threw my-app.js file, up to my-view.js file:
The SDK script I put in index.html, and in the body -> my-app section I inserted:
<body>
<my-app>
<div slot="child">
<div
class="fb-messengermessageus"
messenger_app_id="520865131680985"
page_id="276570696236683"
color="blue"
size="large">
</div>
</div>
</my-app>
...
In the my-app.js file I added to my view the slot:
<my-view name="contacts">
<slot name="child"></slot>
</my-view>
And in my-view.js file I added the unnamed slot:
<div>
<slot></slot>
</div>
In the result the button is rendered on my polymer page :)
It helped me a lot this example and this one.

Related

New google sign in disappears after refreshing page

I followed the guidelines that provided by google to integrate new google sign in. I created HTML using Code generator that provided by Google.
Here I have attached the complete code
<svelte:head>
<title>Home</title>
<meta name="description" content="Svelte demo app" />
</svelte:head>
<section>
<div class="h-screen">
<div
id="g_id_onload"
data-client_id="534101779287-bm07dc8v4ln4kulqbql61nsglcku74vg.apps.googleusercontent.com"
data-context="use"
data-ux_mode="redirect"
data-login_uri="http://localhost:5173/auth/callback"
/>
<div class="bg-red-300 h-80">
<div
class="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="medium"
data-logo_alignment="left"
data-width="180"
/>
</div>
</div>
</section>
It works fine for the first time render of the page.
When we are refreshing the page using Command+R or by clicking reload icon from the browser, Sign in button disappears.
A hard reload is server-side rendered when using SvelteKit. The code is probably incompatible with that or the execution order is wrong.
Check the console for errors and move code that has to run on the client to onMount. You can also turn off server-side rendering for specific pages using the ssr page option as a last resort.
For now I created component using Javascript, Here I have added the answer.
I declared google as global variable in app.d.ts
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
const google: any;
namespace App {
}
}
export {};
I created a svelte file to create a svelte component for sign in button
let canvas: any; //Created a variable to optain a reference to rendered div element
<div class="g_id_signin"
bind:this={canvas}/>
In onMount
onMount(async () => {
google.accounts.id.initialize({
client_id: "534101779287-bm07dc8v4ln4kulqbql61nsglcku74vg.apps.googleusercontent.com",
ux_mode: "redirect",
context: "use",
login_uri: "http://localhost:5173/auth/callback"
});
google.accounts.id.renderButton(canvas, {
width: '220',
theme: 'outline',
size: 'large',
type: 'standard',
text: 'signin_with',
shape: 'rectangular',
logo_alignment: 'left',
});
});
This code will work in initial render, Hard reload (Command+shift+R) and Reload (Command+R)

How can I make this modal dialog open on page load?

I am installing this modal dialog on a client's website, with practically no modifications.
However, I could not find how to make the modal dialog display on page load in the documentation.
Right now it just says:
<!-- Link to open the modal -->
<p>Open Modal</p>
But I am sure there is a way to make it just open on load.
I am using a hosted version of jQuery (jquery.min.js, jquery.modal.min.js) so I'm not trying to add/edit code in the JS file.
http://github.com/kylefox/jquery-modal Method 2: Manually:
$(function() {
$('#login-form').modal();
});
You need to create on your html a div like this:
<div ng-include="'/Somepast/busyModal.html'" ng-show="isLoading"></div>
<div> after load</div>
Then in your javascript you create:
function init() {
$scope.isLoading = true;
SomeFunction().then(function (data) {
$scope.isLoading = false;
}, onError);
};
that's it.

AngularJS dynamic additions to page

We have this AngularJS SP application (smart-mirror) in electron browser, which has user createable extensions.
the extensions are small snippets of html that use angular directives
and use controllers and services.
to install an extension, one has to edit the main page and insert the script tags for the controller and service functions and a <div ng-include= ...> for the snippet of HTML
hardcoded this single page app works great.
but I want to add the capability to this app (opensource) to dynamically load those elements somehow...
adding the tags to the dom works, BUT are not processed correctly.
the HTML is processed before the scripts (from the inserted tags) are run, and when the ng-include inserts the HTML snippet, then controllers are not defined yet...
the body (with the extensions in hard-coded positions commented out)
<body ng-controller="MirrorCtrl" ng-cloak>
<div class="top">
<div class="top-left">
<!-- <div ng-include="'plugins/datetime/index.html'"></div>
<div ng-include="'plugins/calendar/index.html'"></div> -->
</div>
<div class="top-right">
<!-- <div ng-include="'plugins/weather/index.html'"></div>
<div ng-include="'plugins/traffic/index.html'"></div>
<div ng-include="'plugins/stock/index.html'"></div>
<div ng-include="'plugins/tvshows/index.html'"></div>
<div ng-include="'plugins/ha-display/index.html'"></div> -->
</div>
</div>
...
...
<script src="filename.service"/>
<script src= filename.controller"/>
</body>
the calendar extension html (inserted into specific div area of the page)
<ul ng-controller="Calendar" class="calendar fade" ng-show="focus == 'default'" ng-class="config.calendar.showCalendarNames ? 'show-calendar-names' : ''">
<li class="event" ng-repeat="event in calendar" ng-class="(calendar[$index - 1].label != event.label) ? 'day-marker' : ''">
<div class="event-details">
<span class="day">
<span ng-bind="event.startName"></span>
<span ng-if="event.startName != event.endName"> - <span ng-bind="event.endName"></span></span>
</span>
<div class="details calendar-name" ng-bind="event.calendarName"></div>
<span class="summary" ng-bind="event.SUMMARY"></span>
<div class="details" ng-if="event.start.format('LT') != event.end.format('LT')">
<span ng-if="event.startName != event.endName"><span ng-bind="event.start.format('M/D')"></span> <span ng-bind="event.start.format('LT')"></span> - <span ng-bind="event.end.format('M/D')"></span> <span ng-bind="event.end.format('LT')"></span></span>
<span ng-if="event.startName == event.endName"><span ng-bind="event.start.format('LT')"></span> - <span ng-bind="event.end.format('LT')"></span></span>
</div>
<div class="details" ng-if="event.start.format('LT') == event.end.format('LT')">All day</div>
</div>
</li>
</ul>
the calendar extension controller (used by the html)
function Calendar($scope, $http, $interval, CalendarService) {
var getCalendar = function(){
CalendarService.getCalendarEvents().then(function () {
$scope.calendar = CalendarService.getFutureEvents();
}, function (error) {
console.log(error);
});
}
getCalendar();
$interval(getCalendar, config.calendar.refreshInterval * 60000 || 1800000)
}
console.log("registering calendar controller")
angular.module('SmartMirror')
.controller('Calendar', Calendar);
the calendar extension service (used by the controller, shortened for this discussion)
(function () {
'use strict';
function CalendarService($window, $http, $q) {
...
...
return service;
}
console.log("registering calendar service")
angular.module('SmartMirror')
.factory('CalendarService', CalendarService);
} ());
so a user wanting to add an extension would have to create these files,
and edit the main page HTML and insert them
<div ng-include src="filename.html"></div>
in the right place and then add the
<script src="filename.service" >
and
<script src="filename.controller">
in the right place and order, service needs to be done before the controller,
as controller uses service.
anyhow, it's easy to add code to locate all the extensions and dynamically insert elements into the dom in their respective places... but...
in the hard coded, the scripts are added after the html in the body
so, I added a new script (processed when the page is loaded), which locates and inserts all the elements to support the extensions in the right places..
and then the script ends.... (last one in the hard-coded HTML) and the HTML directives are processed and boom, the dynamically added scripts have not been loaded or processed, so the controllers are not found...
I CAN create a temp HTML file with all this info in it and load THAT instead of dealing with the dynamic loading, but I think its better to resolve this
I have tried creating my own angular directive and compiling that in, but get stuck in a loop
<divinc src="filename.service"></divinc>
the inserted div is correct, as a child of the divinc directive
angular.module('SmartMirror')
.directive("divincl", ["$compile" ,function($compile){
return {
priority: 100,
terminal: true,
compile: function(scope, element, attrs) {
var html = "<div ng-include=\"" + element['incl']+ "\" onload='function(){console.log(\'html loaded\')}'></div>"
var templateGoesHere = angular.element(document.getElementById(element['id']));
templateGoesHere.html(html);
//document.body.innerHTML='';
var v= $compile(templateGoesHere);
//scope.$apply();
return function linkFn(scope) {
v(scope) // Link compiled element to scope
}
}
}
}]);
advice on how to solve this problem.. Thanks
In order to make an angularjs 1.7 application load dynamically extensions, there are 2 ways:
either use "nested angularjs applications", which is clearly an advanced use of angularjs and will require you to communicate between 2 angularjs applications, to use $scope.$apply to tell the other app to update etc..
either don't load them dynamically in the frontend, but in your backend when generating the html page which contains the application. Try to list all the extensions from the start.
I recommend you to forget the use of ng-include too, and the fact of trying to add <script></script> inside a directive of your application.
First, you need to re-understand how an angularjs application is started.
When you load your main application, you have a script in which angular.module, angular.directive, angular.value, angular.config, angular.run ... calls are made. This is the declaration step
If you declare a module MyApp and that in your html you have a DOM element with ng-app="MyApp", angularjs will automatically run angular.bootstrap() on this DOM element in order to start MyApp. The execution of the application starts here. You cannot declare anything anymore in the module MyApp.
Secondly, I think that <script></script> code inside templates is sanitized and removed by angular. Plus, even if you execute the code, since the declaration step has finished, you are not supposed to create new directives or register new services, it won't work.
A good way is that when you load your plugin, you:
Load the script of the plugin from the start, it must declare a new module like MyPlugin1.
In the directive which will contain the plugin, put the code of the link I sent you, which makes possible to insert a sub-application. In the end you will have a <div ng-app="MyPlugin1"></div> inside your directive's template
Then call angular.bootstrap on that node, which will make possible to start the sub application.
If you do this, you can run the sub application, but you didn't pass it parameters. In order to pass it parameters, you can put the code of the module MyPlugin1 inside a function, in order to have an application factory. Then use app.value('param1', parameter1) to initialize the app.
For example:
function declarePlugin1(myParam1, myParam2) {
var app = angular.module('MyPlugin1', []);
// app.directive();
app.value('myParam1', myParam1);
app.value('myParam2', myParam2);
}
And inside the directive call declarePlugin1("test", 42);, which will declare the application MyPlugin1 with the initialized values, and then angular.bootstrap to tell angularjs to start this application.
You can pass callbacks too, in order to communicate between the 2 applications.

Add dynamic text to ToolTip in Html ActionLink using ASP.NET

I have a web application with a HTML Action link. My requirement is to have a mouse hover / Tool tip to the action link where the details of corresponding HTML Action links has to be displayed when mouse is placed over the link.
Following is the HTML Action link
<td> #Html.ActionLink(#item.Split('.')[0], "myMethod", new { name = item }, new { Class = "action add", title ="My Tooltip"})</td>
I want to call a method from here that returns the corresponding details and the details has to be shown as a tool tip to the users.
Help me in resolving this issue.Thanks in advance!!!
Here is the JQuery plugin to do a Tooltip. It will attach to the control's title attribute as you would like.
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$( function() {
$( document ).tooltip();
} );
</script>
Codepen example: https://codepen.io/anon/pen/xmOaKJ
For the dynamic piece and with the assumption your model has a Title property, you should be able to handle it like so:
#Html.ActionLink(#item.Split('.')[0], "myMethod", new { name = item }, new { #class = "action add", #title = item.Title})

On html.actionlink click, load a partial view below the link

Currently in my view this is what I have
<dt>Credit Saldo</dt>
<dd>#Model.CreditSaldo #Html.ActionLink("Add Credit","AddCredit",routeValues:new{Model.LicenseId})</dd>
<br/>
<dd>
<div id="partialDiv"></div>
</dd>
Whenever User clicks Add Credit, currently it forwards me to new partial view (no surprise).
What I want to do is load that partial view in same view, in the div that has Id as partialdiv.
Here is the method in controller, thats being called when the link is called
[HttpGet]
public ActionResult AddCredit(Guid licenseid)
{
var newCredit = new AddCredits();
return PartialView(newCredit);
}
and this is what I've done in partial view
#model AdminPortal.Areas.Customer.Models.ViewModels.AddCredits
<div class="input-small">#Html.EditorFor(m=>m.CreditToAdd) <button class="btn-small" type="submit">Add</button></div>
How can I load the partial view in same view when the link "Add Credit" is clicked?
Edit 1 : Tried Ajax
<dt>Credit Saldo</dt>
<dd>#Model.CreditSaldo #Ajax.ActionLink("Add Credit","AddCredit",new{Model.LicenseId}, new AjaxOptions {UpdateTargetId = "partialDiv"})
<br/>
<dd>
<div id="partialDiv"></div>
</dd>
Result: Partial View still loads as new view (not in same view)
You can use the ajax helpers for that
#Ajax.ActionLink("Add Credit","AddCredit",routeValues:new{Model.LicenseId}, new AjaxOptions {UpdateTagetId = "partialDiv"}, new {})
In order for these to work, you will need to make sure that you load jquery and jquery.unobtrusive-ajax in your layout.
When including jquery, use a pre 1.9 version or the scripts won't work. If you need a version of jquery 1.9+ add the jquery.migrate package from nuget to your project and load that in your layout too.