app-localize-behavior and shared localization cache - localization

According to the polymer documentation for app-localize-behavior
Each element that displays content to be localized should add Polymer.AppLocalizeBehavior. All of these elements share a common localization cache, so you only need to load translations once.
In the following snippet (adapted from this answer) does not find the shared resources in the tag
Maybe I missed something ?
<!DOCTYPE html>
<html>
<head>
<base href="https://polygit.org/polymer+:master/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<script src="https://rawgit.com/yahoo/intl-messageformat/d361003/dist/intl-messageformat.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="app-localize-behavior/app-localize-behavior.html">
</head>
<body>
<x-local-translate></x-local-translate>
<dom-module id="x-local-translate">
<template>
<div>
<span title="english">🇬🇧</span>
<paper-toggle-button on-change="_toggle" id="switch"></paper-toggle-button>
<span title="french">🇫🇷</span>
</div>
<div>
<h4>Outside Repeater</h4>
<div>
<div>{{localize('greeting')}}</div>
</div>
<h4>Template Repeater Items</h4>
<template is="dom-repeat" items="{{things}}">
<div>{{localize('greeting')}}</div>
</template>
<x-local-test></x-local-test>
</div>
</template>
<script>
Polymer({
is: "x-local-translate",
behaviors: [
Polymer.AppLocalizeBehavior
],
properties: {
things: {
type: Array,
value: function() {
return [1, 2, 3];
}
},
/* Overriden from AppLocalizeBehavior */
language: {
value: 'en',
type: String
},
/* Overriden from AppLocalizeBehavior */
resources: {
type: Object,
value: function() {
return {
'en': {
'greeting': 'Hello!'
},
'fr': {
'greeting': 'Bonjour!'
}
};
}
}
},
_toggle: function() {
this.language = this.$.switch.checked ? 'fr' : 'en';
}
});
</script>
</dom-module>
<dom-module id="x-local-test">
<template>
<h4>Inside x-local-test</h4>
<div>{{localize('greeting')}}</div>
</template>
<script>
Polymer({
is: "x-local-test",
behaviors: [
Polymer.AppLocalizeBehavior
],
properties: {
things: {
type: Array,
value: function() {
return [1, 2, 3];
}
}
},
});
</script>
</dom-module>
</body>
</html>
Now in the following fiddle, I made it work by passing the resources and language object as x-local-test properties.
https://jsfiddle.net/g4evcxzn/2/
But it should work without that

According the ideas of Jose A. and Jean-Rémi here some example code for copy/paste:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/app-localize-behavior/app-localize-behavior.html">
<script>
MyLocalizeBehaviorImpl = {
properties: {
language: {
value: 'de'
}
},
attached: function() {
this.loadResources(this.resolveUrl('locales.json'));
}
};
MyLocalizeBehavior = [MyLocalizeBehaviorImpl, Polymer.AppLocalizeBehavior];
</script>
Include the behavior file in all your custom components and add the behavior:
<link rel="import" href="./my-localize-behavior.html">
......
behaviors: [
MyLocalizeBehavior
],

I took a look at AppLocaleBehavior's demo and if you actually look at the repo, they use two elements for it, one that loads the resources from an external json and one more that has them locally defined and in the demo, the don't seem to be sharing a cache, just as what's happening to you.
This struck me as odd seeing that they do mention the cache, so I took a look at the behavior's code and found out something interesting, the cache actually exists but it seems its purpose is to prevent loading the same external resource multiple times rather than sharing the resources property.
So, if you want to share localization resources on multiple elements the way to go would be having a common resource (let's say we call it locales.json) and call the loadResources function on every one of them (Since the request is cached you don't need to worry about loading the file multiple times). You could do it on the attached callback like this:
attached: function () {
this.loadResources(this.resolveUrl('locales.json'));
}

Related

How to use KaTeX auto-renderer in dynamically changing HTML?

I have two beginner questions about using KaTeX auto-renderer. Both are related to the code below.
My first question: Do I need to use document.body in renderMathInElement? Can it be called only on the paragraph with id formula? If yes, how? I tried several ways, but nothing worked. Probably I just don't know the correct syntax.
My second question: After pressing the button, the changed text is not rendered. How and where shall I call renderMathInElement again to look for the new formulas in the page? Again, I tried several ways (including calling it right after changing the text), nothing worked.
<!DOCTYPE html>
<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex#0.11.1/dist/katex.min.css" integrity="sha384-zB1R0rpPzHqg7Kpt0Aljp8JPLqbXI3bhnPWROx27a9N0Ll6ZP/+DiW/UqRcLbRjq" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex#0.11.1/dist/katex.min.js" integrity="sha384-y23I5Q6l+B6vatafAwxRu/0oK/79VlbSz7Q9aiSZUvyWYIYsd+qj+o24G5ZU2zJz" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex#0.11.1/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(document.body, {
// ...options...
});
});
</script>
</head>
<body>
<p id="formula">Consider the circle with equation \(x^2+y^2=25\).</p>
<button onclick="myFunction()">Change text</button>
<script>
function myFunction() {
var x = document.getElementById("formula");
x.innerHTML = "Find the definite integral \(\int_0^1 xdx.\)";
}
</script>
</body>
</html>
Yes, you can call renderMathInElement for any DOM element, e.g. the one you get for document.getElementById("formula").
Calling renderMathInElement(x) essentially does what you want. Except that you also need to escape the backslashes in your JavaScript string literal by doubling them.
Taken together you get something like this:
let opts = {
// ...options...
}
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(document.getElementById("formula"), opts);
});
function myFunction() {
var x = document.getElementById("formula");
x.innerHTML = "Find the definite integral \\(\\int_0^1 xdx.\\)";
renderMathInElement(x, opts);
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex#0.11.1/dist/katex.min.css" integrity="sha384-zB1R0rpPzHqg7Kpt0Aljp8JPLqbXI3bhnPWROx27a9N0Ll6ZP/+DiW/UqRcLbRjq" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex#0.11.1/dist/katex.min.js" integrity="sha384-y23I5Q6l+B6vatafAwxRu/0oK/79VlbSz7Q9aiSZUvyWYIYsd+qj+o24G5ZU2zJz" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex#0.11.1/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"></script>
<p id="formula">Consider the circle with equation \(x^2+y^2=25\).</p>
<button onclick="myFunction()">Change text</button>

Allow Dropzone js to upload only zip files

In my mvc net core app I need to implement drag&drop files uploader. I found Dropzone js and hoping to use it in my purposes. But can't configure it, I need to allow it upload ony zip files.
My code:
<div class="row">
<div class="col-md-9">
<div id="dropzone">
<form action="/Home/Upload" class="dropzone needsclick dz-clickable" id="uploader">
<div class="dz-message needsclick">
Drop files here or click to upload.<br>
</div>
</form>
</div>
</div>
</div>
<script>
$(document).ready(function () {
Dropzone.options.uploader = {
paramName: "file",
maxFilesize: 256,
acceptedFiles: "application/zip,application/octet-stream,application/x-zip-compressed,multipart/x-zip,.zip",
maxFiles: 1
};
});
</script>
Also of course I have controller:
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
var uploads = Path.Combine(_environment.ContentRootPath, "Uploads");
if (file.Length > 0)
{
using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
return RedirectToAction("Index");
}
But still, application allows to upload any file with any MIME type. Where is a problem?
Also restriction of maxFiles isn't working too - it allows me to upload infinite count of files.
You can use option of dropzone.js name acceptedfile.
Dropzone.options.myAwesomeDropzone = {
....
acceptedFiles: ".zip",
....
};
According to the documentation (https://www.dropzonejs.com/#configuration), you can do it like this:
Dropzone.options.myAwesomeDropzone = {
accept: function(file, done) {
if (file.name.endsWith !== ".zip") {
done("Naha, you don't.");
}
else { done(); }
}
};
A function that gets a file and a done function as parameters. If the
done function is invoked without arguments, the file is "accepted" and
will be processed. If you pass an error message, the file is rejected,
and the error message will be displayed. This function will not be
called if the file is too big or doesn't match the mime types.
Edit:
Here is a fiddle to demonstrate it: http://jsfiddle.net/behyzjng/15/
Set acceptedFiles: 'application/zip' in defaultOptions
Here are the documentation for you to work on Dropzone.js:
Github: https://github.com/dropzone/dropzone
Docs: https://docs.dropzone.dev
check all avaliable options at https://github.com/dropzone/dropzone/blob/main/src/options.js
check the desired extensions allowed and write the MIME type as a value of acceptedFiles at https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
Working solution here:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/dropzone#5/dist/min/dropzone.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/dropzone#5/dist/min/dropzone.min.css" type="text/css" />
<title>Document</title>
</head>
<body>
<style>
.my-dropzone {
width: 100%;
height: 100px;
border: 1px dashed;
display: flex;
align-items: center;
justify-content: center;
}
</style>
<div class="my-dropzone">
Drag and drop zip files here, or click here to upload.
</div>
<script>
// Dropzone.js
// Github: https://github.com/dropzone/dropzone
// Docs: https://docs.dropzone.dev
// check all avaliable options at
// https://github.com/dropzone/dropzone/blob/main/src/options.js
const defaultOptions = {
url: "/file/post",
// check the desired extensions allowed and write the MIME type as a value of acceptedFiles at
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
acceptedFiles: 'application/zip'
};
// Dropzone has been added as a global variable.
const dropzone = new Dropzone("div.my-dropzone", defaultOptions);
</script>
</body>
</html>

video.js not working properly with jquery mobile

I am trying to use video.js(gitHub link - https://github.com/videojs/video.js ) plugin in my jquery mobile project to get custom video player, I followed all the documentation from this site (http://videojs.com/), but due to some reasons I am getting following errors -
The element or ID supplied is not valid. (videojs).
this[a] is not a function.
My code -
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="Js/jquery.js"></script>
<script src="Js/jquery.signalR-2.1.2.min.js"></script>
<script src="Js/jquery.mobile-1.4.5.js"></script>
<link href="mcss/jquery.mobile-1.4.5.css" rel="stylesheet" />
<link href="http://vjs.zencdn.net/4.12/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/4.12/video.js"></script>
<script type="text/javascript">
videojs("Mobile_VIDEO_1").ready(function () {
var vid = this;
vid.on("ended", function () {
alert("is");
$("#videoListXYZ").css("display", "block");
});
});
</script>
</head>
<body>
<div data-role="page" id="p-forget-password">
<div data-role="main" class="ui-content ui-body-cf ui-responsive">
<!-- inserted dyanamically using handlebars template "http://handlebarsjs.com"/ -->
<video id="Mobile_VIDEO_1" class="video-js vjs-default-skin" controls data-id="{{VideoId}}" data-setup='{ "plugins" : { "resolutionSelector" : { "default_res" : "360" } } }' autoplay="autoplay" width="340" height="250">
<source src="{{Path}}" type="video/mp4" data-res="360" />
</video>
</div>
</div>
</body>
Please help me to find out what I am doing wrong.
-I tried using putting videojs(xyx).ready(....) inside document.ready
- I also tried sending my script at the bottom of my page as suggested by (http://help.videojs.com/discussions/problems/985-api-ready-call-fails), but it still not working
After many hit and trial, I realized that my event is firing much before the DOM initialization, so I searched for how to check when the whole page is fully loaded and I come across this document (https://css-tricks.com/snippets/jquery/run-javascript-only-after-entire-page-has-loaded/) from this link I used this
$(window).bind("load", function() {
// code here
});
to check if my page is fully loaded or not . my final solution is mentioned below , if any of you come across a better solution then please share that to help others.
$(window).bind("load", function () {
var videoPath = $('#sv1').attr('src'); //to get the path of video
if (videoPath != "" && videoPath != null) { //checking for non-empty path
console.log(videoPath);
videojs('MY_VIDEO_1', { "plugins": { "resolutionSelector": { "default_res": "360" } } }, function () {
console.log('Good to go!');
this.play();
this.on('ended', function () {
console.log('awww...over so soon?');
$("#videoList").css("display", "block");
});
});
$("#replay").click(function () {
var myPlayer = videojs("MY_VIDEO_1");
myPlayer.play();
});
}
});

add selected item in kendo Multiselect after load

Here is the reference
Example of Server filtering in Kendo UI MultiSelect widget
Now the thing is, I want to add selected item after it's being loaded. Since the data source is remote (acts like autocomplete), I can't attach it directly
<!DOCTYPE html>
<html>
<head>
<base href="http://demos.telerik.com/kendo-ui/multiselect/serverfiltering">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2015.2.902/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2015.2.902/styles/kendo.material.min.css" />
<script src="//kendo.cdn.telerik.com/2015.2.902/js/jquery.min.js"></script>
<script src="//kendo.cdn.telerik.com/2015.2.902/js/kendo.all.min.js"></script>
</head>
<body>
<div id="example" >
<div class="demo-section k-header">
<h4>Products</h4>
<select id="products"></select>
</div>
<script>
$(document).ready(function() {
$("#products").kendoMultiSelect({
placeholder: "Select products...",
dataTextField: "airline_name",
dataValueField: "airline_value",
autoBind: false,
dataSource: {
serverFiltering: true,
transport: {
read: {
url: "/**Server url **/",
}
}
}
});
intially dataSource is empty ...Multiselect is loaded
when is execute following code:
$("#products").data("kendoMultiSelect").value([{airline_name:"AA", airline_value:"BB"}]);
//above statemnt doesnt display in selected value but shows value when called value() function
});
</body>
</html>
THE URL gets JSON Array and it works like when I enter letter that is sent to controller and controller send requested matched values in JSON array.
Now I cannot use below statement to add selected items:
$("#products").data("kendoMultiSelect").values(json_array) //doesnt work
THERE IS NO DATASOURCE AT MULTISELECT LOAD . IN My case VALUES ARE NOT LOADED ALREADY . The above is just an example
In the following code snippet you can see your example working. It is basically your code with button that selects two of the elements of the DataSource.
What you should do is define json_array as an array of the ids (in your case ProductID) if you want to select them using the text field (Chai, Aniseed Syrup..., then you should define in kendoMultiSelect that the dataValueField is ProductName and not ProductId.
$(document).ready(function() {
$("#products").kendoMultiSelect({
placeholder: "Select products...",
dataTextField: "ProductName",
dataValueField: "ProductID",
autoBind: false,
dataSource: {
type: "odata",
serverFiltering: true,
transport: {
read: {
url: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Products",
}
}
}
});
$("#sel").on("click", function() {
$("#products").data("kendoMultiSelect").value([3, 1]);
});
});
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2015.2.902/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="//kendo.cdn.telerik.com/2015.2.902/styles/kendo.material.min.css" />
<script src="//kendo.cdn.telerik.com/2015.2.902/js/jquery.min.js"></script>
<script src="//kendo.cdn.telerik.com/2015.2.902/js/kendo.all.min.js"></script>
<button id="sel" class="k-button">Select Chai & Aniseed</button>
<h4>Products</h4>
<select id="products"></select>

angular directive compile order

I was trying to write a simple directive to generate a (potentially) more complex dom element. I am quite confused about what is going on here but I think the directive I use inside my directive get linked first? Anyway the element I am generating is not visible where it should.
Sorry for all that confusion, here is the plunkr:
http://plnkr.co/edit/vWxTmA1tQ2rz6Z9dJyU9?p=preview
I think the directive I use inside my directive get linked first?
Yes. A child directive's link function will execute before the parent's link function.
Here is a fiddle that shows two nested directives,
<div d1>
<div d2></div>
</div>
and it logs when the directives' controller and link functions are called.
There are a few issues with your Plunker:
Since you are using # for your isolate scopes, you need to use {{}}s in your attribute values:
<visible value='{{visible}}'>plop</visible>
<invisible value='{{visible}}'>plop</invisible>
Since $scope.visible is defined in your controller, I assume you meant to use that value, and not test.
In the invisible directive, you need to use isolate scope property value in your link function. Property visible is available to the transcluded scope (which is in affect if you use a template in your directive like #Langdon has) but not the isolate scope, which is what the link function sees.
var template = "<span ng-show='value'>{{value}}</span>";
Plunker.
If you want a simple directive, you're better off letting Angular do most of the work through ngTransclude, and $watch.
http://plnkr.co/edit/xYTNIUKYuHWhTrK80qKJ?p=preview
HTML:
<!doctype html>
<html ng-app="app">
<head>
<meta charset="utf-8">
<title>trying to compile stuff</title>
<script src="http://code.angularjs.org/1.1.1/angular.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="AppCtrl">
<input type="checkbox" ng-model="test" id="test" /><label for="test">Visibility (currently {{test}})</label>
<br />
<br />
<visible value='test'>visible tag</visible>
<invisible value='test'>invisible tag</invisible>
</div>
</body>
</html>
JavaScript:
angular
.module('app', [])
.controller('AppCtrl', function($scope) {
$scope.test = false;
})
.directive('visible', function() {
return {
restrict: 'E',
transclude: true,
template: '<span ng-transclude></span>',
replace: true,
scope: {
value: '='
},
link: function(scope, element, attrs) {
console.log(attrs);
scope.$watch('value', function (value) {
element.css('display', value ? '' : 'none');
});
console.log(attrs.value);
}
};
})
.directive('invisible', function() {
return {
restrict: 'E',
transclude: true,
template: '<span ng-transclude></span>',
replace: true,
scope: {
value: '='
},
link: function(scope, element, attrs) {
scope.$watch('value', function (value) {
element.css('display', value ? 'none' : '');
});
}
};
});

Resources