jwPlayer causes rendering not to load in Sitecore's Page Editor - sitecore

I'm currently working on a rendering in Sitecore 7.2 (MVC) that will show a jwPlayer given a link to a video (either in the Media Library or from an external source, like YouTube). When I add the rendering (with a valid data source) through Presentation Details in the Content Editor everything looks fine, and works perfectly. The trouble that I'm running into right now, though, is that when I try to do the same thing from the Page Editor (with the exact same rendering and data source), nothing is showing up in that placeholder at all.
The part of the rendering that deals with the video is as follows:
#if (Model.VideoLink != null && Model.Image != null)
{
var vidid = Guid.NewGuid().ToString();
<div class="article-video-module">
<p class="video-placeholder-text">#Html.Raw(Model.Heading)</p>
<div id="#vidid">Loading the player...</div>
<script type="text/javascript">
jwplayer("#vidid").setup({
file: "#Model.VideoLink.Url",
image: "#Model.Image.Src",
width: "100%",
aspectratio: "16:9",
sharing: {
link: "#Model.VideoLink.Url"
},
primary: 'flash'
});
jwplayer('videodiv-#vidid').onPlay(function () {
$(this.container).closest('.fullbleed-video-module').find('.video-placeholder-text').hide();
});
jwplayer('videodiv-#vidid').onPause(function () {
$(this.container).closest('.fullbleed-video-module').find('.video-placeholder-text').show();
});
</script>
</div>
#Editable(a => Model.Description)
}
Other things that might help:
When I comment out everything in the <script> tag above the rendering shows up perfectly.
A reference to jwplayer.js is found on the page (that was my first thought)
Console errors in Javascript:
No suitable players found and fallback enabled on jwplayer.js
Uncaught TypeError: undefined is not a function on jwplayer("#vidid").setup({ and on jwplayer('videodiv-#vidid').onPlay(function () { from above.
How can I get jwPlayer and Page Editor to work nicely with each other?

The issue is that when you add a component through Page Editor, the script is fired before the div <div id="#vidid"> element is added to DOM. Don't ask me why...
The solution is really simple: wrap your javascript code with if condition, checking if the div is already there:
<script type="text/javascript">
if (document.getElementById("#vidid")) {
jwplayer("#vidid").setup({
file: "#Model.VideoLink.Url",
image: "#Model.Image.Src",
width: "100%",
aspectratio: "16:9",
sharing: {
link: "#Model.VideoLink.Url"
},
primary: 'flash'
});
jwplayer('videodiv-#vidid').onPlay(function () {
$(this.container).closest('.fullbleed-video-module').find('.video-placeholder-text').hide();
});
jwplayer('videodiv-#vidid').onPause(function () {
$(this.container).closest('.fullbleed-video-module').find('.video-placeholder-text').show();
});
}
</script>
There is also another issue with your code - Guid can start with number, and this is not a valid id for html elements. You should change your code to:
var vidid = "jwp-" + Guid.NewGuid().ToString();

I wouldn't rule out a conflict with the version of JQuery that the Page Editor uses - this usually messes stuff up. There's a good post here on to overcome the issues.
http://jrodsmitty.github.io/blog/2014/11/12/resolving-jquery-conflicts-in-page-editor/

Related

Wkhtmltopdf does not render Chart.JS 2.5.0 graph

Using:
WKpdftohml version 0.12.3.2
PHPwkhtmltopdf version 2.2.0
Chart.JS version 2.5.0
I'm trying to print a line graph using the above libraries. I can reproduce a pdf using the shell command: wkhtmltopdf --javascript-delay 5000 " http://netdna.webdesignerdepot.com/uploads7/easily-create-stunning-animated-charts-with-chart-js/chartjs-demo.html" test2.pdf
So there is no problem with WKhtmltopdf.
The problem is when I do it in my app, using the PHPwkhtmltopdf library. I get a blank page.
From my research these are the things I tried:
Added 'javascript-delay' => 500 to Chart.JS options;
Added animation:{onComplete: function () {window.JSREPORT_READY_TO_START =true} to Chart.JS options;
Added <div style="width:800px;height:200;font-size:10px;"> to the parent div of canvas html tag
Added ctx.canvas.width = 800;ctx.canvas.height = 200; to javascript initialization of the chart.
Well nothing worked. I love Chart.JS and WKhtmltopdf, but if I can't print I'll have to drop one of them. Is there any solution?
This is my php code for the PHPwkhtmltopdf:
public function imprimir ($request, $response)
{
// include_once 'config/constants.php';
// include_once 'resources/auxiliar/helpers.php';
$folha = $_POST['printit'];
$variaveis = explode(',', $folha);
$nomeFicheiro = $variaveis[0];
$printName = substr($nomeFicheiro, 5);
if (isset($variaveis[2])) {
$_SESSION['mesNumero'] = $variaveis[2];
$_SESSION['mes'] = $variaveis[1];
} else {
$mesNumero = 0;
$mes = '';
}
ob_start();
if ($nomeFicheiro == 'printPpiam') {
require ('C:/xampp/htdocs/.../'.$nomeFicheiro.'.php');
} else {
require ('C:/xampp/htdocs/.../'.$nomeFicheiro.'.php');
}
$content = ob_get_clean();
// You can pass a filename, a HTML string, an URL or an options array to the constructor
$pdf = new Pdf($content);
// On some systems you may have to set the path to the wkhtmltopdf executable
$pdf->binary = 'C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf';
$pdf -> setOptions(['orientation' => 'Landscape',
'javascript-delay' => 500,
// 'enable-javascript' => true,
// 'no-stop-slow-scripts' => true]
]);
if (!$pdf->send($printName.'.pdf')) {
throw new Exception('Could not create PDF: '.$pdf->getError());
}
$pdf->send($printName.'.pdf');
}
# Update 1
Made a php file with the page output. Run it in the browser and the graph rendered. When I do it in the console it renders everything except the graph!
How can it be wkhtmltopdf renders the graphics in this page : http://netdna.webdesignerdepot.com/uploads7/easily-create-stunning-animated-charts-with-chart-js/chartjs-demo.html but not my own?!
# Update 2
After Quince's comment, I tried just turning the animations off, but I'm not sure on how to do that. I tried:
$pdf -> setOptions(['orientation' => 'Landscape',
'javascript-delay' => 500,
// 'window-status' => 'myrandomstring ',
'animation' => false,
'debug-javascript',
'no-stop-slow-scripts',
]);
But it fails.
Here's the code that works with wkhtmltopdf version 0.12.5:
chart.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<style>
.reportGraph {width:900px}
</style>
</head>
<body>
<div class="reportGraph"><canvas id="canvas"></canvas></div>
<script type="text/javascript">
// wkhtmltopdf 0.12.5 crash fix.
// https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192
'use strict';
(function(setLineDash) {
CanvasRenderingContext2D.prototype.setLineDash = function() {
if(!arguments[0].length){
arguments[0] = [1,0];
}
// Now, call the original method
return setLineDash.apply(this, arguments);
};
})(CanvasRenderingContext2D.prototype.setLineDash);
Function.prototype.bind = Function.prototype.bind || function (thisp) {
var fn = this;
return function () {
return fn.apply(thisp, arguments);
};
};
function drawGraphs() {
new Chart(
document.getElementById("canvas"), {
"responsive": false,
"type":"line",
"data":{"labels":["January","February","March","April","May","June","July"],"datasets":[{"label":"My First Dataset","data":[65,59,80,81,56,55,40],"fill":false,"borderColor":"rgb(75, 192, 192)","lineTension":0.1}]},
"options":{}
}
);
}
window.onload = function() {
drawGraphs();
};
</script>
</body>
</html>
Run:
$ wkhtmltopdf chart.html chart.pdf:
Loading pages (1/6)
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done
Found the answer. After I created a separate file, outside the framework, i did some tests again. It rendered the graph in the browser so I tried to use the command tool WKhtmltopdf, and it did not worked, when it did with other examples (see Update #1). So there is something wrong with my php page.
Ran the same tests that I did in the framework, and got the answer for my problem. By introducing a parent div tag width dimensions in the canvas tag it made the graph render in the page.
<div style="width:800px;height:200;">
<canvas id="myChart" style="width:800px;height:200;"></canvas>
</div>
The proposition was found in this site: Github, so thanks laguiz.
Try adding this, as according to this github source
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.0.0/polyfill.min.js"></script>
Solved it by downgrading wkhtmltopdf: 0.12.4 > 0.12.2.1
chart.js version seemed to have no influence. I used 2.7.0.
Fixed width and height seem to be required as well.
Edit: Since wkhtmltopdf is dead, I switched to Puppeteer recently.
I was dealing with the same issue using rotativa to export my ASP.NET MVC page with Chart.JS to PDF with no luck.
After a couple of days I finally found a super-easy solution to achieve my goal. What I did is simply to use the .toBase64Image() method of Chart.JS to encode the chart to a base64 string variable in Javascript. Then I saved this string into a model and then on the PDF html page a used tag where i put the base64encoded string to a scr property and the result is great :-)
javascript:
//save Chart as Image
var url_base64 = document.getElementById('myChart').toDataURL('image/png');
//set the string as a value of a hidden element
document.getElementById('base64graph').value = url_base64;
PDF view:
<img style='display:block; width:900px;height:400px;position:relative;margin:auto;text-align:center;' id='base64image'
src='#Model.base64graph' />
I'm trying to improve on the answer by temuri, which is great, but a bit bloated. I ran into the OP's issues (even same WKpdftohml version) and this did the trick for me:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<div style="width: 400px;"><canvas id="canvas"></canvas></div>
<script type="application/javascript">
// wkhtmltopdf 0.12.5 crash fix.
// https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192
Function.prototype.bind = Function.prototype.bind || function (thisp) {
const fn = this;
return function () {
return fn.apply(thisp, arguments);
};
};
new Chart(
document.getElementById("canvas"), {
"responsive": false,
"type":"line",
"data":{"labels":["January","February","March","April","May","June","July"],"datasets":[{"label":"My First Dataset","data":[65,59,80,81,56,55,40],"fill":false,"borderColor":"rgb(75, 192, 192)","lineTension":0.1}]},
"options":{}
}
);
</script>
I'm yet to figure out how to get the chart library via ordinary tools like npm, instead of getting it via ajax like here in the first line. Note that this can impact your chart resolution.
I was strugling with that too and you self-answer did not help my case. I am using symfony 3.3 and Chart.js 2 and whatever I did, did not work properly. So I have solved it in a different manner (maybe not a clean one) and I wanted to post it here for inspiration to others.
I needed to export a page, that I was presenting to the user in a browser. In browser, I used Javascript to get picture out of the rendered graph with
animation: {
onComplete: function(animation) {
console.log('done');
var url=document.getElementById("barChartByCountryWeight{{ part }}{{ subsetKey }}").toDataURL();
$.ajax({
url: 'saveChartImages',
type: 'POST',
data: { 'barChartByCountryWeight{{ part }}{{ subsetKey }}': url },
success: function(result) {
console.log(result);
console.log('the request was successfully sent to the server');
},
error: function (request, error) {
console.log(arguments[0]['responseText']);
console.log(" Can't do because: " + error);
}
});
}
}
And on server side I put it in session and in a controller for the PDF export, I have taken the image from session and put the image in the HTML, that is converted to PDF.
Hope that helps.
I have implemented the working code for this issue. You can check out the working code here.
NOTE: For generating pdf you must disable the Chart JS animation or add the option javascript-delay=>1000 to the wkhtmltopdf options.
I have solved this problem when I tried to use Chartjs 1 instead of a new chart js. The reason for this is because laravel snappy uses wkhtmltopdf, which doesn't support css animation, while new chartjs uses css animation.
This github issue shows that.
The solution i found is to use google chart instead. It also uses svg, so you can get high resolution charts.

Emberjs outlet inside a bootstrap popover

I'm using bootstrap popover in my app and I need to render an outlet inside it.
I have this nested route :
this.resource('pages', function(){
this.resource('page', { path: ':id' }, function(){
this.resource('edit', function(){
this.resource('images', function(){
this.resource('image', { path: ':image_id'}, function(){
this.route('edit');
})
});
});
});
});
When the user is here => /pages/1/edit/ when he click on an image it route to /images but render the {{outlet}} inside the popover like this :
<div class="popover-content hide">
{{outlet}}
</div>
This is my popover initialisation :
$img.popover({
html: true,
content: function() {
return $('.popover-content').html(); //need to have the outlet here
}
});
So far, it render correctly my outlet, but inside the images template, I have some button that modify the DOM and it doesn't update the html. Unless if I close and open the popover again I can see the modification.
Is it possible to render the outlet directly inside the code ? or is it possible to have my popover being updated ?
Thanks for the help.
See these links for an alternative approach to putting Ember stuff in Bootstrap popovers:
Bootstrap Popovers with ember.js template
https://cowbell-labs.com/2013-10-20-using-twitter-bootstrap-js-widgets-with-ember.html
Ember and Handlebars don't like this because it's basically copying the html content of a div and plopping it into another. But that html alone isn't everything that's needed. Ember is magic and there's lots of stuff happening in the background.
Your hidden div is real ember stuff, so let's try not to mess with it by calling .html() on it. My idea is to literally move the DOM itself instead.
first, modify your popover function call to always create this placeholder div:
content: '<div id="placeholder"></div>',
next, detach the content div from the dom in the didInsertElement of the view:
// get the popover content div and remove it from the dom, to be added back later
var content = Ember.$('.popover-content').detach();
// find the element that opens your popover...
var btn = Ember.$('#btn-popup-trigger').get(0);
// ... and whenever the popover is opened by this element being clicked, find the placeholder div and insert the content element
// (this could be improved. we really just want to know when the popover is opened, not when the button is clicked.)
btn.addEventListener("click", function() {
content.appendTo("#placeholder");
});
since the content div is immediately detached when didInsertElement is called, you can remove the "hide" css class from the content div.
edit: i tried this on my own project and it broke two-way binding. the controller updated my handlebars elements, but any two-way bound {{input}} helpers did not update the controller/model. i ended up using a single-item dropdown menu, and used this to prevent the menu from closing too quickly:
Twitter Bootstrap - Avoid dropdown menu close on click inside

Tooltip added by DOM manipulation is unable to render HTML

I am attempting to render the HTML in a tooltip, but unfortunately its not working at all.
This is how it has been programmed:
<div class="someField"></div>
<script>
$(function () {
$('.someField').append('(Example)');
$("body").tooltip({html:true,selector: '[data-toggle=tooltip]'});
});
</script>
I have set data-html="true" in the link and furthermore enabled html in the tooltip parameter.
Whats wrong with my code?
UPDATE:
Bootstrap v2.3.1 is used for this project (old framework).
Try this:
$("body").tooltip({ html: true, selector: '[data-toggle="tooltip"]' });
WORKING DEMO

Remember preferable language

I've made a simple website for my daughter.
It is in Dutch and for every page there is a English version as well.
Dutch URL: nl/index.html
English URL: eng/index.html
What I would like to do is give the visitor the option to set one language as preference. So if they come to this site the next time they will automatically linked to the preferable page.
I know this can be done with a cookie and saw the explanation on this forum ( How to remember the currently clicked url? javascript?PHP? ).
I've tried to make this work but apparently I am doing something wrong?
Can somebody guide me through step by step? That would be great!
Kind regards,
Jurgen
If you are familiar with jQuery you can use the cookies plug-in to persist the user's language choice and redirect him to the appropriate page every time he comes back to your site. Bellow is a sample code that uses two buttons to set the language:
First you declare the jQuery scripts (I use to store them in a Script folder, hence the following):
<script type="text/javascript" src="../Script/jquery-1.7.2.js"></script>
<script type="text/javascript" src="../Script/jquery.cookie.js"></script>
Then you define the page ready event like this:
$(function () {
var url = 'your_url';
var english_page = 'eng/index.html';
var dutch_page = 'nl/index.html';
if ($.cookie('default_page') != null) {
if (window.location.href != url + '/' + $.cookie('default_page')) {
window.location.href = url + '/' + $.cookie('default_page');
}
}
$('#set_english_butt').click(function () {
$.cookie('default_page', english_page, { expires: 999 });
alert('English was set as the default language');
});
$('#set_dutch_butt').click(function () {
$.cookie('default_page', dutch_page, { expires: 999 });
alert('Dutch was set as the default language');
});
});
Which is hooked to some html buttons in you page:
<div>
<span>Select your language:</span>
<button id="set_english_butt">English</button>
<button id="set_dutch_butt">Dutch</button>
</div>

How to run function after view finish render change [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Using Ember.js, how do I run some js after a view is rendered?
I use JWPlayer to show video on my site and JWPlayer use javascript to create viewer.
I have to run JWPlayer script after my hidden view change to show.
jwplayer('video_space').setup({
'flashplayer': 'player.swf',
'file': 'http://content.longtailvideo.com/videos/flvplayer.flv',
'controlbar': 'bottom',
'width': '470',
'height': '320'
});
I binding my view with value on controller
<script type="text/x-handlebars" >
{{#view Food.previewView }}
Video session
<div {{bindAttr class="showPreview"}}>
<div id='video_space'>Video Loading...</div>
</div>
{{#view SC.Button target="Food.appController" action="show"}}
show
{{/view}}
{{/view}}
</script>
My javascript for all controller and view
Food = Ember.Application.create();
Food.appController = Ember.Object.create({
showVideo: false,
show: function(){
Food.previewView.set('showVideo', true);
}
});
Food.previewView = Ember.View.extend({
showVideoBinding: 'Food.appController.showVideo',
showPreview: function() {
return this.get('showVideo') ? "show" : "hide";
}.property('showVideo')
});
If I run JWPlayer script when change "showVideo" variable the video will error because $('#video_space') is still hidden.
Emberjs have some delegate method like "afterViewChange" or "viewDidChange" ?
testing code
http://jsfiddle.net/apirak/Ay6Fh/
Override the Ember.View.didInsertElement function and place your customizations in there.
http://docs.emberjs.com/#doc=Ember.View&method=didInsertElement&src=false
One thing, you did an error when you created your appController, when creating objects you need to use .create instead of .extend, this mistake was causing the button to don't find the "show" action of you controller.
That said, you can still bind on showVideo for you actions, and when it changes you can call your JWPlayer script to show it up.