I have this JSON coming in to typeahead:
[{"q": "#django", "count": 3}, {"q": "#hashtag", "count": 3}, {"q": "#hashtags", "count": 0}, {"q": "#google", "count": 1}]
And the code of my file to work with typeahead
var hashTags = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('q'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: '/hashtag.json?q=%QUERY',
remote: {
url: '/hashtag.json?q=%QUERY',
wildcard: '%QUERY'
}
});
$('.search-tag-query').typeahead({
hint:true,
highlight: true,
// autoselect: true,
minLength:1,
limit: 10,
},
{
name: 'hashTags',
display: 'q',
// displayKey: 'count',
source: hashTags.ttAdapter(),
templates: {
empty: 'No results...'
}
});
I easily render to my html dropdown suggestions the data that I get from the "q" or the "count".
The problem is that I cant send both of them, as you can see in the code.
How can I send both, so I can show the tags and the count of posts related to them?
Thanks.
Use a custom template
suggestion: function(data) {
return '<p><strong>' + data.q+ '</strong> – ' + data.count+ '</p>';
}
You can concatenate the arrays returned at Bloodhound using $.map() and Array.prototype.concat().
You can then filter suggestions at suggestion property of templates object passed to .typeahead(). At stacksnippets both q and count properties are appended to HTML as suggestions for each match of either q or count values.
$(function() {
var data = [{"q": "#django", "count": 3}, {"q": "#hashtag", "count": 3}, {"q": "#hashtags", "count": 0}, {"q": "#google", "count": 1}];
var suggestions = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
local: $.map(data, function(d) {
return {
value: d.q,
suggest: d
}
})
// here we concatenate the two arrays
.concat($.map(data, function(d) {
return {
value: d.count,
suggest: d
}
}))
});
suggestions.initialize();
$(".bs-example .typeahead").typeahead({
minLength: 1,
hint: true,
highlight: true
}, {
name: "suggestions",
displayKey: "value",
templates: {
suggestion: function(data) {
console.log(data);
var details = "<div class=resultContainer>"
+ data.value
+ "<br>"
+ (data.suggest.count == data.value
? data.suggest.q
: data.suggest.count)
+ "</div>";
return details
}
},
source: suggestions.ttAdapter()
});
})
.bs-example {
font-family: sans-serif;
position: relative;
margin: 100px;
}
.typeahead,
.tt-query,
.tt-hint {
border: 2px solid #CCCCCC;
border-radius: 8px;
font-size: 24px;
height: 30px;
line-height: 30px;
outline: medium none;
padding: 8px 12px;
width: 200px;
}
.typeahead {
background-color: #FFFFFF;
}
.typeahead:focus {
border: 2px solid #0097CF;
}
.tt-query {
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
}
.tt-hint {
color: #999999;
}
.tt-dropdown-menu {
background-color: #FFFFFF;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 8px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
margin-top: 12px;
padding: 8px 0;
width: 422px;
}
.tt-suggestion {
font-size: 24px;
line-height: 24px;
padding: 3px 20px;
}
.tt-suggestion.tt-is-under-cursor {
background-color: #0097CF;
color: #FFFFFF;
}
.tt-suggestion p {
margin: 0;
}
.resultDesc,
.resultLabel {
font-size: 14px;
font-style: italic;
}
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://twitter.github.io/typeahead.js/releases/latest/typeahead.bundle.js"></script>
<div class="bs-example">
<input type="text" class="typeahead tt-query" placeholder="q and count" />
</div>
Thank's to everyone, now I understand how it works and specially to Madalin Ivascu. I improved my code and it worked by this way:
var hashTags = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('q'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: '/hashtag.json?q=%QUERY',
remote: {
url: '/hashtag.json?q=%QUERY',
wildcard: '%QUERY'
}
});
$('.search-tag-query').typeahead({
hint:true,
highlight: true,
// autoselect: true,
minLength:1,
limit: 10,
},
{
name: 'hashTags',
display: 'q',
// displayKey: 'count',
source: hashTags.ttAdapter(),
templates: {
// empty: 'No results...',
suggestion: function (data) {
return '<p><strong>' + data.q + '</strong> – ' + data.count + '</p>';
}
}
});
Related
I'm tryin to recreate this photo below and I am so close. I have run into a problem and I cannot seem to fix it. In my Snippet the text is not vertical aligned with the other container divs like they are in the photo. How can I align my text so the words are aligned? I have tried using flex box but because some text are longer/shorter then others they are all out of alignment because their positions are fixed.
const storeItems = [
{
name: 'TV',
price: 800.00,
inStock: true,
details: '4K Ultra HD'
},
{
name: 'Phone',
price: 700.00,
inStock: false,
details: '5G'
},
{
name: 'Game Console',
price: 300.00,
inStock: true,
details: 'The latest and greatest'
},
{
name: 'Laptop',
price: 1200.00,
inStock: true,
details: '16GB RAM 1TB SSD'
},
{
name: 'Smart Watch',
price: 200.00,
inStock: false,
details: 'Counts your steps'
},
{
name: 'Headphones',
price: 100.00,
inStock: true,
details: 'Clearest music to be heard'
},
{
name: 'Keyboard',
price: 100.00,
inStock: true,
details: 'Types for you'
},
{
name: 'HDMI Cord',
price: 100.00,
inStock: true,
details: 'HDMI to USB type C'
},
{
name: 'Monitor',
price: 300.00,
inStock: true,
details: '4K Ultra HD'
},
{
name: 'Speaker',
price: 200.00,
inStock: true,
details: 'Clearest music to be heard'
},
{
name: 'Video Game',
price: 60.00,
inStock: true,
details: 'Enjoy for hours'
},
];
storeItems.forEach(function(n, i, a) {
if (n.inStock == true) {
$('.boxes').append('<div class="container">' + '<p>$' + n.price +'</p>' + '<p>' + n.name + '</p>' + '<p>' + n.details + '</p>'
+
'</div>');
}
if (n.inStock == false) {
$('.boxes').append('<p class="notInStock">' + n.name + ': $' +
n.price + ' Not in stock' + '</p>');
}
})
$('#clickMe').appendTo('.boxes');
$('#clickMe').click(function(){
$('#contentContainer').toggleClass('darkModeBackground');
$('.container').toggleClass('darkModeContainers');
$(this).toggleClass('darkModeClickMe');
})
body {
font-family: Helvetica;
background-color: #d3d3d3;
color: black;
}
.shrink-container {
width: 800px;
height: 50px;
margin: 0 auto;
}
.container {
display: flex;
align-content: center;
justify-content: space-between;
align-items: center;
background-color: white;
padding: 0px 10px;
margin: 10px 0;
border-radius: 5px;
}
#clickMe {
display: inline-block;
padding: 10px;
font-family: Helvetica;
border-radius: 3px;
border: 1px solid;
}
#clickMe:hover{
cursor: pointer;
}
.inStock{
}
.notInStock{
display:none;
}
.darkModeBackground{
background-color: black;
color:white;
}
.darkModeContainers{
background-color: #5A5A5A;
color: white;
}
.darkModeClickMe{
border-color: white;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>List of items</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body id="contentContainer">
<div class="shrink-container">
<div id="header">
<h1>Products</h1>
<p>______
<p>
</div>
<div id="appendToMe">
<div class="boxes">
</div>
</div>
</div>
<div id="clickMe">Toggle Dark Mode</div>
<script src="https://code.jquery.com/jquery-3.5.0.slim.min.js" integrity="sha256-MlusDLJIP1GRgLrOflUQtshyP0TwT/RHXsI1wWGnQhs=" crossorigin="anonymous"></script>
<script src="app.js"></script>
</body>
</html>
A solution using <table>.
const storeItems = [
{
name: 'TV',
price: 800.00,
inStock: true,
details: '4K Ultra HD'
},
{
name: 'Phone',
price: 700.00,
inStock: false,
details: '5G'
},
{
name: 'Game Console',
price: 300.00,
inStock: true,
details: 'The latest and greatest'
},
{
name: 'Laptop',
price: 1200.00,
inStock: true,
details: '16GB RAM 1TB SSD'
},
{
name: 'Smart Watch',
price: 200.00,
inStock: false,
details: 'Counts your steps'
},
{
name: 'Headphones',
price: 100.00,
inStock: true,
details: 'Clearest music to be heard'
},
{
name: 'Keyboard',
price: 100.00,
inStock: true,
details: 'Types for you'
},
{
name: 'HDMI Cord',
price: 100.00,
inStock: true,
details: 'HDMI to USB type C'
},
{
name: 'Monitor',
price: 300.00,
inStock: true,
details: '4K Ultra HD'
},
{
name: 'Speaker',
price: 200.00,
inStock: true,
details: 'Clearest music to be heard'
},
{
name: 'Video Game',
price: 60.00,
inStock: true,
details: 'Enjoy for hours'
},
];
storeItems.forEach(function(n, i, a) {
$('#appendToMe').append('<tr><td>$' + n.price +'</td><td>' + n.name + '</td><td>' + n.details + '</td></tr>');
})
$('#clickMe').click(function(){
$('body').toggleClass('darkModeBackground');
$('#appendToMe').toggleClass('dark');
$(this).toggleClass('darkModeClickMe');
})
body {
font-family: Helvetica;
background-color: #d3d3d3;
color: black;
}
#appendToMe {
border-spacing: 0 .5em;
margin-bottom: 2em;
}
tr {
background-color: white;
}
td {
padding: 10px 20px;
}
td:first-child {
border-radius: 5px 0 0 5px;
}
td:last-child {
border-radius: 0 5px 5px 0;
}
#clickMe button {
padding: 10px;
font-family: Helvetica;
border-radius: 3px;
border: 1px solid;
}
.darkModeBackground {
background-color: black;
color:white;
}
#appendToMe.dark tr {
background-color: #5A5A5A;
color: white;
}
.darkModeClickMe {
border-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<h1>Products</h1>
<table id="appendToMe"></table>
<div id="clickMe"><button>Toggle Dark Mode</button></div>
</body>
I'm trying to use a property of my data in a computed method like this:
data() {
return {
ToDoItems: [
{ id: uniqueId("todo-"), label: "Learn Vue", done: false },
{
id: uniqueId("todo-"),
label: "Create a Vue project with the CLI",
done: true,
},
{ id: uniqueId("todo-"), label: "Have fun", done: true },
{ id: uniqueId("todo-"), label: "Create a to-do list", done: false },
],
};
},
computed: {
listSummary() {
const numberFinishedItems = this.ToDoItems.filter((item) => item.done)
.length;
return `${numberFinishedItems} out of ${this.ToDoItems.length} items completed`;
},
},
But the IDE (Visual Studio Code) and the compiler throw an error:
Property 'ToDoItems' does not exist on type 'ComponentPublicInstance<{}, {}, {}, {}, {}, EmitsOptions, {}, {}, false, ComponentOptionsBase<{}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string, {}>>'.
I'm following the vue.js tutorial of mozilla (https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties#adding_a_summary_counter) but using v3.
Has anything changed that this isn't possible anymore / differently?
Thanks in advance
complete code:
<template>
<div id="app">
<h1>To-Do List</h1>
<to-do-form #todo-added="addToDo"></to-do-form>
<h2 id="list-summary">{{ listSummary }}</h2>
<ul aria-labelledby="list-summary" class="stack-large">
<li v-for="item in ToDoItems" :key="item.id">
<to-do-item :label="item.label" :done="true" :id="item.id"></to-do-item>
</li>
</ul>
</div>
</template>
<script lang="ts">
import uniqueId from "lodash.uniqueid";
import { defineComponent } from "vue";
import ToDoItem from "./components/ToDoItem.vue";
import ToDoForm from "./components/ToDoForm.vue";
export default defineComponent({
name: "App",
components: {
ToDoItem,
ToDoForm,
},
data() {
return {
ToDoItems: [
{ id: uniqueId("todo-"), label: "Learn Vue", done: false },
{
id: uniqueId("todo-"),
label: "Create a Vue project with the CLI",
done: true,
},
{ id: uniqueId("todo-"), label: "Have fun", done: true },
{ id: uniqueId("todo-"), label: "Create a to-do list", done: false },
],
};
},
methods: {
addToDo(toDoLabel: string) {
this.ToDoItems.push({
id: uniqueId("todo-"),
label: toDoLabel,
done: false,
});
},
},
computed: {
listSummary() {
const numberFinishedItems = this.ToDoItems.filter((item) => item.done)
.length;
return `${numberFinishedItems} out of ${this.ToDoItems.length} items completed`;
},
},
});
</script>
<style>
/* Global styles */
.btn {
padding: 0.8rem 1rem 0.7rem;
border: 0.2rem solid #4d4d4d;
cursor: pointer;
text-transform: capitalize;
}
.btn__danger {
color: #fff;
background-color: #ca3c3c;
border-color: #bd2130;
}
.btn__filter {
border-color: lightgrey;
}
.btn__danger:focus {
outline-color: #c82333;
}
.btn__primary {
color: #fff;
background-color: #000;
}
.btn-group {
display: flex;
justify-content: space-between;
}
.btn-group > * {
flex: 1 1 auto;
}
.btn-group > * + * {
margin-left: 0.8rem;
}
.label-wrapper {
margin: 0;
flex: 0 0 100%;
text-align: center;
}
[class*="__lg"] {
display: inline-block;
width: 100%;
font-size: 1.9rem;
}
[class*="__lg"]:not(:last-child) {
margin-bottom: 1rem;
}
#media screen and (min-width: 620px) {
[class*="__lg"] {
font-size: 2.4rem;
}
}
.visually-hidden {
position: absolute;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px);
clip: rect(1px, 1px, 1px, 1px);
clip-path: rect(1px, 1px, 1px, 1px);
white-space: nowrap;
}
[class*="stack"] > * {
margin-top: 0;
margin-bottom: 0;
}
.stack-small > * + * {
margin-top: 1.25rem;
}
.stack-large > * + * {
margin-top: 2.5rem;
}
#media screen and (min-width: 550px) {
.stack-small > * + * {
margin-top: 1.4rem;
}
.stack-large > * + * {
margin-top: 2.8rem;
}
}
/* End global styles */
#app {
background: #fff;
margin: 2rem 0 4rem 0;
padding: 1rem;
padding-top: 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 2.5rem 5rem 0 rgba(0, 0, 0, 0.1);
}
#media screen and (min-width: 550px) {
#app {
padding: 4rem;
}
}
#app > * {
max-width: 50rem;
margin-left: auto;
margin-right: auto;
}
#app > form {
max-width: 100%;
}
#app h1 {
display: block;
min-width: 100%;
width: 100%;
text-align: center;
margin: 0;
margin-bottom: 1rem;
}
</style>
Boussadjra Brahim's answer is "alright" but it doesn't actually address the issue. user16362509 is correct, but doesn't answer the question.. What you need to do is yes, annotate the return types of both your data properties and computed properties so TS knows what's going on. Not only that, but it provides stricter type checking if you annotate all types. I don't believe this issue actually occurs when properly using Vue3's composition API, but the problem does, as you can see, exist in options Api. Try: (Or consider using Composition Api). Weirdly enough, when you annotate the return type of a computed method, it understands the context, just quirks of Vue but it's good practice to have the types explicit.
<script lang="ts">
import uniqueId from "lodash.uniqueid";
import { defineComponent } from "vue";
import ToDoItem from "./components/ToDoItem.vue";
import ToDoForm from "./components/ToDoForm.vue";
export default defineComponent({
name: "App",
components: {
ToDoItem,
ToDoForm,
},
data(): { ToDoItems: Array<{id: *string*, label: string, done: boolean}> } {
return {
ToDoItems: [
{ id: uniqueId("todo-"), label: "Learn Vue", done: false },
{
id: uniqueId("todo-"),
label: "Create a Vue project with the CLI",
done: true,
},
{ id: uniqueId("todo-"), label: "Have fun", done: true },
{ id: uniqueId("todo-"), label: "Create a to-do list", done: false },
],
};
},
methods: {
addToDo(toDoLabel: string): void {
this.ToDoItems.push({
id: uniqueId("todo-"),
label: toDoLabel,
done: false,
});
},
},
computed: {
listSummary(): string {
const numberFinishedItems = this.ToDoItems.filter((item) => item.done)
.length;
return `${numberFinishedItems} out of ${this.ToDoItems.length} items completed`;
},
},
});
</script>
You are already using Vue 3. Why not use composition API with script setup for even better typescript support?
Live demo
<template>
<div id="app">
<h1>To-Do List</h1>
<form #submit.prevent="addToDo">
<input type="text" ref="label" />
<button type="submit">Add</button>
</form>
<h2 id="list-summary">{{ listSummary }}</h2>
<ul aria-labelledby="list-summary" class="stack-large">
<li v-for="item in ToDoItems" :key="item.id">
<input type="checkbox" v-model="item.done" />
{{ item.id }} {{ item.label }}
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
interface ToDoItem {
id: string;
label: string;
done: boolean;
}
const label = ref(null)
const ToDoItems = ref<ToDoItem[]>([
{ id: 1, label: 'Learn Vue', done: false },
{ id: 2, label: 'Create a Vue project with the CLI', done: true },
{ id: 3, label: 'Have fun', done: true },
{ id: 4, label: 'Create a to-do list', done: false },
]);
const addToDo = () => {
ToDoItems.value.push({
id: ToDoItems.value.length + 1,
label: label.value.value,
done: false,
});
label.value.value = '';
};
const listSummary = computed(() => {
return `${ToDoItems.value.filter((item) => item.done).length} out of ${ToDoItems.value.length} items completed`;
});
</script>
I have angular 8 application and I can show a popup.
But I want to style the popup. But how to do that?
SO I have this template:
<mgl-layer
*ngIf="imageLoaded"
id="camera"
type="symbol"
[source]="{
type: 'geojson',
data: {
type: 'FeatureCollection',
}
}"
(click)= "onClick($event)"
[layout]="{'icon-image': 'camera', 'icon-size': 0.25}"
>
</mgl-layer>
<mgl-popup *ngIf="selectedPoint" [feature]="selectedPoint">
<span [innerHTML]="selectedPoint.properties?.description"></span>
</mgl-popup>
and ts:
allWifiPoints = this.wifiPoints.map((wifi) => ({
type: 'Feature',
properties: {
description:
// eslint-disable-next-line max-len
},
geometry: {
type: 'Point',
coordinates: wifi,
},
}));
onClick(evt: MapLayerMouseEvent) {
this.selectedPoint = evt.features![0];
}
and css:
.mapboxgl-popup-content-wrapper {
width: 89px;
}
but nothing change. The popup stays white
see image.
So what I have to change?
Thank you
So in css: toggle-layer.component.scss
I have this:
:host ::ng-deep .mapboxgl-popup-content-wrapper {
width: 89px;
}
Should work:
:host ::ng-deep .mapboxgl-popup-content-wrapper {
width: 89px;
height: max-content;
border: 2px solid #BF0404;
background-color: rgba(243, 207, 207, 0.7);
border-radius: 18px;
margin-bottom: 3px;
}
I am using given code to export html page to pdf by using drawDom method:
$(function(){
$('#ExportToPdf').on("click", function (e) {
var selectedTab = $('.selected-tab').attr("id");
selectedTab = selectedTab.replace("tab-", "#");
var fileName = $(selectedTab).find($('.report-title')).text().replace(' ', '_');
kendo.drawing.drawDOM($(selectedTab))
.then(function (group) {
// Render the result as a PDF file
return kendo.drawing.exportPDF(group, {
paperSize: "auto",
margin: { left: "1cm", top: "1cm", right: "1cm", bottom: "1cm" }
});
})
.done(function (data) {
// Save the PDF file
kendo.saveAs({
dataURI: data,
fileName: fileName + ".pdf"
});
});
});
});
But result is given below for Arabic characters
I want this result:
I tried every thing what I get on internet.
Adding different types of fonts for unicode and kendo builtin fonts but all in vein.
This question is 8 months old, so you might have found a solution by now.
I just wanted to share my own solution, which is a bit of a hack, but at least it works for me.
Basically, you want to flip the text in the html using the special command:
For example - grid.client.name (grid.client.name is just an example, replace with where you store the arabic names. Repeat for each cell that contains arabic text).
You will notice now that the text in the pdf is no longer shrinked - but it actually has the wrong direction now. How to fix this? - well,
you simply reverse the arabic text in the code (so basically we reverse the text twice). An example method to reverse a string:
function reverseString(str) {
var newString = "";
for (var i = str.length - 1; i >= 0; i--) {
newString += str[i];
}
return newString;
}
Apply this to all of your data that contains arabic text.
If you've done both of these things, it should now appear correctly after exporting to pdf.
Good Luck.
Here is KENDO UI tutorial and it works fine for me.Can you rewrite your code by analyze this code? If the problem is still continue then we try to find solution again.
<script>
// Import DejaVu Sans font for embedding
// NOTE: Only required if the Kendo UI stylesheets are loaded
// from a different origin, e.g. cdn.kendostatic.com
kendo.pdf.defineFont({
"DejaVu Sans" : "https://kendo.cdn.telerik.com/2016.2.607/styles/fonts/DejaVu/DejaVuSans.ttf",
"DejaVu Sans|Bold" : "https://kendo.cdn.telerik.com/2016.2.607/styles/fonts/DejaVu/DejaVuSans-Bold.ttf",
"DejaVu Sans|Bold|Italic" : "https://kendo.cdn.telerik.com/2016.2.607/styles/fonts/DejaVu/DejaVuSans-Oblique.ttf",
"DejaVu Sans|Italic" : "https://kendo.cdn.telerik.com/2016.2.607/styles/fonts/DejaVu/DejaVuSans-Oblique.ttf",
"WebComponentsIcons" : "https://kendo.cdn.telerik.com/2017.1.223/styles/fonts/glyphs/WebComponentsIcons.ttf"
});
</script>
<!-- Load Pako ZLIB library to enable PDF compression -->
<script src="https://kendo.cdn.telerik.com/2017.2.621/js/pako_deflate.min.js"></script>
<script>
$(document).ready(function() {
$(".export-pdf").click(function() {
// Convert the DOM element to a drawing using kendo.drawing.drawDOM
kendo.drawing.drawDOM($(".content-wrapper"))
.then(function(group) {
// Render the result as a PDF file
return kendo.drawing.exportPDF(group, {
paperSize: "auto",
margin: { left: "1cm", top: "1cm", right: "1cm", bottom: "1cm" }
});
})
.done(function(data) {
// Save the PDF file
kendo.saveAs({
dataURI: data,
fileName: "HR-Dashboard.pdf",
proxyURL: "https://demos.telerik.com/kendo-ui/service/export"
});
});
});
$(".export-img").click(function() {
// Convert the DOM element to a drawing using kendo.drawing.drawDOM
kendo.drawing.drawDOM($(".content-wrapper"))
.then(function(group) {
// Render the result as a PNG image
return kendo.drawing.exportImage(group);
})
.done(function(data) {
// Save the image file
kendo.saveAs({
dataURI: data,
fileName: "HR-Dashboard.png",
proxyURL: "https://demos.telerik.com/kendo-ui/service/export"
});
});
});
$(".export-svg").click(function() {
// Convert the DOM element to a drawing using kendo.drawing.drawDOM
kendo.drawing.drawDOM($(".content-wrapper"))
.then(function(group) {
// Render the result as a SVG document
return kendo.drawing.exportSVG(group);
})
.done(function(data) {
// Save the SVG document
kendo.saveAs({
dataURI: data,
fileName: "HR-Dashboard.svg",
proxyURL: "https://demos.telerik.com/kendo-ui/service/export"
});
});
});
var data = [{
"source": "Approved",
"percentage": 237
}, {
"source": "Rejected",
"percentage": 112
}];
var refs = [{
"source": "Dev",
"percentage": 42
}, {
"source": "Sales",
"percentage": 18
}, {
"source": "Finance",
"percentage": 29
}, {
"source": "Legal",
"percentage": 11
}];
$("#applications").kendoChart({
legend: {
position: "bottom"
},
dataSource: {
data: data
},
series: [{
type: "donut",
field: "percentage",
categoryField: "source"
}],
chartArea: {
background: "none"
},
tooltip: {
visible: true,
template: "${ category } - ${ value } applications"
}
});
$("#users").kendoChart({
legend: {
visible: false
},
seriesDefaults: {
type: "column"
},
series: [{
name: "Users Reached",
data: [340, 894, 1345, 1012, 3043, 2013, 2561, 2018, 2435, 3012]
}, {
name: "Applications",
data: [50, 80, 120, 203, 324, 297, 176, 354, 401, 349]
}],
valueAxis: {
labels: {
visible: false
},
line: {
visible: false
},
majorGridLines: {
visible: false
}
},
categoryAxis: {
categories: [2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011],
line: {
visible: false
},
majorGridLines: {
visible: false
}
},
chartArea: {
background: "none"
},
tooltip: {
visible: true,
format: "{0}",
template: "#= series.name #: #= value #"
}
});
$("#referrals").kendoChart({
legend: {
position: "bottom"
},
dataSource: {
data: refs
},
series: [{
type: "pie",
field: "percentage",
categoryField: "source"
}],
chartArea: {
background: "none"
},
tooltip: {
visible: true,
template: "${ category } - ${ value }%"
}
});
$("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Customers"
},
pageSize: 15,
group: { field: "ContactTitle" }
},
height: 450,
groupable: true,
sortable: true,
selectable: "multiple",
reorderable: true,
resizable: true,
filterable: true,
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
columns: [
{
field: "ContactName",
template: "<div class=\'customer-name\'>#: ContactName #</div>",
title: "Contact",
width: 200
},{
field: "ContactTitle",
title: "Contact Title",
width: 220
},{
field: "Phone",
title: "Phone",
width: 160
},{
field: "CompanyName",
title: "Company Name"
},{
field: "City",
title: "City",
width: 160
}
]
});
});
</script>
<style>
/*
Use the DejaVu Sans font for display and embedding in the PDF file.
The standard PDF fonts have no support for Unicode characters.
*/
.k-widget {
font-family: "DejaVu Sans", "Arial", sans-serif;
font-size: .9em;
}
</style>
<style>
.export-app {
display: table;
width: 100%;
height: 750px;
padding: 0;
}
.export-app .demo-section {
margin: 0 auto;
border: 0;
}
.content-wrapper {
display: table-cell;
vertical-align: top;
}
.charts-wrapper {
height: 250px;
padding: 0 0 20px;
}
#applications,
#users,
#referrals {
display: inline-block;
width: 50%;
height: 240px;
vertical-align: top;
}
#applications,
#referrals {
width: 24%;
height: 250px;
}
.customer-photo {
display: inline-block;
width: 40px;
height: 40px;
border-radius: 50%;
background-size: 40px 44px;
background-position: center center;
vertical-align: middle;
line-height: 41px;
box-shadow: inset 0 0 1px #999, inset 0 0 10px rgba(0,0,0,.2);
}
.customer-name {
display: inline-block;
vertical-align: middle;
line-height: 41px;
padding-left: 10px;
}
</style>
<!DOCTYPE html>
<html>
<head>
<base href="https://demos.telerik.com/kendo-ui/pdf-export/index">
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.common-material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.material.min.css" />
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.material.mobile.min.css" />
<script src="https://kendo.cdn.telerik.com/2017.2.621/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2017.2.621/js/jszip.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2017.2.621/js/kendo.all.min.js"></script>
</head>
<body>
<div id="example">
<div class="box wide hidden-on-narrow">
<h4>Export page content</h4>
<div class="box-col">
<button class='export-pdf k-button'>Export as PDF</button>
</div>
<div class="box-col">
<button class='export-img k-button'>Export as Image</button>
</div>
<div class="box-col">
<button class='export-svg k-button'>Export as SVG</button>
</div>
</div>
<div class="demo-section k-content export-app wide hidden-on-narrow">
<div class="demo-section content-wrapper wide">
<div class="demo-section charts-wrapper wide">
<div id="users"></div>
<div id="applications"></div>
<div id="referrals"></div>
</div>
<div id="grid"></div>
</div>
</div>
<div class="responsive-message"></div>
</div>
</body>
</html>
I made temporary solution that I convert the report into canvas then I exported to pdf. I html2canvas to export html in to canvas. if any one find another solution please let me know.
$('#ExportToPdf').on("click", function (e) {
html2canvas(document.querySelector("#widget-47")).then(canvas => {
$("#widget-47").hide();
$("#widget-47").parent().append(canvas);
});
setTimeout(function () {
kendo.drawing.drawDOM($('#kendo-wrapper'))
.then(function (group) {
// Render the result as a PDF file
return kendo.drawing.exportPDF(group, {
paperSize: "auto",
margin: { left: "1cm", top: "1cm", right: "1cm", bottom: "1cm" }
});
})
.done(function (data) {
// Save the PDF file
kendo.saveAs({
dataURI: data,
fileName: "report.pdf"
});
$("#widget-47").siblings().remove();
$("#widget-47").show();
});
}, 3000);
});
Going for a sort-of Windows explorer-style drag-and-drop folder behavior here. The "// make chapter items droppable" block isn't working - specifically, it's not appending the draggable to the dragged folder's list.
<html>
<head>
<script src="js/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="js/jquery-ui-1.7.2.custom.min.js" type="text/javascript"></script>
<style>
ul
{
margin: 0;
padding: 0;
}
ul#chapter_list
{
background: #fff;
}
#chapter_list li
{
list-style-type: none;
position: relative;
}
#chapter_list li .sortable_handle
{
cursor: move;
padding: 2px .5em 5px 5px;
position: relative;
top: -2px;
left: -5px;
}
span.chapter_title
{
cursor: pointer;
padding-left: 36px !important;
background: url(http://www.openwebgraphics.com/resources/data/2296/22x22_folder_orange_open.png) no-repeat 8px 50%;
}
.comic_chapter div, .comic_page
{
border: 2px solid black;
margin-bottom: 1px;
padding: 3px 5px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
}
li.comic_chapter ul
{
padding: 2px 2px 2px 1em;
margin: 3px;
}
#chapter_list li.drop_highlight div
{
background: darkBlue;
color: white;
}
.comic_chapter div
{
background: LightBlue;
}
.comic_page
{
background: #fff;
}
.chapter-placeholder
{
border: 2px dashed LightBlue;
margin: 2px;
}
.page-placeholder
{
height: 1.6em;
border: 2px dashed #666;
margin: 2px;
}
</style>
</head>
<body>
<script type="text/javascript" />
var chapter_list = {
0 : {
'chapter_title' : 'Un-Chaptered',
'chapter_pages' : {}
},
1 : {
'chapter_title' : 'Chapter 1',
'chapter_pages' : {
1 : {
'page_title' : 'Page 1'
},
2 : {
'page_title' : 'Page 2'
},
3 : {
'page_title' : 'Page 3'
},
4 : {
'page_title' : 'Page 4'
},
5 : {
'page_title' : 'Page 5'
},
6 : {
'page_title' : 'Page 6'
}
}
},
2 : {
'chapter_title' : 'Chapter 2',
'chapter_pages' : {
7 : {
'page_title' : 'Page 7'
},
8 : {
'page_title' : 'Page 8'
},
9 : {
'page_title' : 'Page 9'
},
10 : {
'page_title' : 'Page 10'
}
}
},
3 : {
'chapter_title' : 'Chapter 3',
'chapter_pages' : {
11 : {
'page_title' : 'Page 11'
},
12 : {
'page_title' : 'Page 12'
}
}
}
};
document.write('<ul id="chapter_list">');
for (i in chapter_list) {
chapter = chapter_list[i];
document.write('<li id="chapter_' + i + '" class="comic_chapter">' +
'<div>' +
'<span class="sortable_handle">||</span>');
if (i > 0) document.write('<input type="checkbox" />');
document.write('<span class="chapter_title">' + chapter.chapter_title + '</span>' +
'</div>' +
'<ul id="chapter_' + i + '_pages">');
for (n in chapter.chapter_pages) {
page = chapter.chapter_pages[n];
document.write('<li id="page_' + n + '" class="comic_page">' +
'<span class="sortable_handle">||</span>' +
'<label for="page_' + n + '_chk">' +
'<input type="checkbox" id="page_' + n + '_chk" />' +
' <span class="page_title">' + page.page_title + '</span>' +
'</label>' +
'</li>');
}
document.write('</ul>' +
'</li>');
}
document.write('</ul>');
</script>
<div id="debug"></div>
<script type="text/javascript">
// hide Chapter contents
$('.comic_chapter ul').hide();
// add onClick => toggle chapter-contents visibility
$('.chapter_title').bind('click', function(e){
$(this).parents('li.comic_chapter').children('ul').toggle();
});
// make Chapters sortable
$('#chapter_list').sortable({
handle: 'div .sortable_handle',
placeholder: 'chapter-placeholder',
forcePlaceholderSize: true
}).disableSelection();
// make Pages sortable
$('.comic_chapter ul').sortable({
handle: '.sortable_handle',
placeholder: 'page-placeholder',
connectWith: '.comic_chapter ul' // allow pages to be dragged between chapters
}).disableSelection();
$('.comic_chapter ul').droppable({
greedy: true
});
// make chapter items droppable
$('#chapter_list').children('li').droppable({
accept: '.comic_page',
hoverClass: 'drop_highlight',
drop: function(e, ui) {
$(this).children('ul').append(ui.draggable);
}
});
</script>
</body>
</html>
Thanks.
I see that you have droppables, but where are the draggables? Droppables accept draggables, not just static html (because, really, nothing is being dropped in that case)