PrimeNG Editor Math Formulas - primeng

I have a simple math formula which I need to display on the editor by using the formula button.
My formula: {a^2 + b^2}
When I try to give it, get an error:
EXCEPTION: [Parchment] Unable to create formula blot
ErrorHandler</ErrorHandler.prototype.handleError http://localhost:8080/prod/vendor.js:31109:14
PlatformRef_</PlatformRef_.prototype._bootstrapModuleFactoryWithZone/</<.next http://localhost:8080/prod/vendor.js:36067:70
EventEmitter</EventEmitter.prototype.subscribe/schedulerFn< http://localhost:8080/prod/vendor.js:31736:41
SafeSubscriber</SafeSubscriber.prototype.__tryOrUnsub http://localhost:8080/prod/vendor.js:41339:14
SafeSubscriber</SafeSubscriber.prototype.next http://localhost:8080/prod/vendor.js:41288:18
Subscriber</Subscriber.prototype._next http://localhost:8080/prod/vendor.js:41241:10
Subscriber</Subscriber.prototype.next http://localhost:8080/prod/vendor.js:41205:14
Subject</Subject.prototype.next http://localhost:8080/prod/vendor.js:40828:18
EventEmitter</EventEmitter.prototype.emit http://localhost:8080/prod/vendor.js:31722:59
NgZone</NgZone.prototype.triggerError http://localhost:8080/prod/vendor.js:32083:61
NgZone</NgZone.prototype.forkInnerZoneWithAngularBehavior/this.inner<.onHandleError http://localhost:8080/prod/vendor.js:32044:22
ZoneDelegate.prototype.handleError http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:196:19
Zone.prototype.runTask http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:128:25
ZoneTask/this.invoke http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:293:28
ORIGINAL STACKTRACE:
ErrorHandler</ErrorHandler.prototype.handleError http://localhost:8080/prod/vendor.js:31114:18
PlatformRef_</PlatformRef_.prototype._bootstrapModuleFactoryWithZone/</<.next http://localhost:8080/prod/vendor.js:36067:70
EventEmitter</EventEmitter.prototype.subscribe/schedulerFn< http://localhost:8080/prod/vendor.js:31736:41
SafeSubscriber</SafeSubscriber.prototype.__tryOrUnsub http://localhost:8080/prod/vendor.js:41339:14
SafeSubscriber</SafeSubscriber.prototype.next http://localhost:8080/prod/vendor.js:41288:18
Subscriber</Subscriber.prototype._next http://localhost:8080/prod/vendor.js:41241:10
Subscriber</Subscriber.prototype.next http://localhost:8080/prod/vendor.js:41205:14
Subject</Subject.prototype.next http://localhost:8080/prod/vendor.js:40828:18
EventEmitter</EventEmitter.prototype.emit http://localhost:8080/prod/vendor.js:31722:59
NgZone</NgZone.prototype.triggerError http://localhost:8080/prod/vendor.js:32083:61
NgZone</NgZone.prototype.forkInnerZoneWithAngularBehavior/this.inner<.onHandleError http://localhost:8080/prod/vendor.js:32044:22
ZoneDelegate.prototype.handleError http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:196:19
Zone.prototype.runTask http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:128:25
ZoneTask/this.invoke http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:293:28
e#http://localhost:8080/node_modules/quill/dist/quill.min.js:7:13845
n#http://localhost:8080/node_modules/quill/dist/quill.min.js:7:12290
l</e.prototype.insertAt#http://localhost:8080/node_modules/quill/dist/quill.min.js:7:25329
j</<.value#http://localhost:8080/node_modules/quill/dist/quill.min.js:9:4946
s</e.prototype.insertAt#http://localhost:8080/node_modules/quill/dist/quill.min.js:7:5404
s</e.prototype.insertAt#http://localhost:8080/node_modules/quill/dist/quill.min.js:7:21442
x</<.value#http://localhost:8080/node_modules/quill/dist/quill.min.js:10:5543
q</<.value#http://localhost:8080/node_modules/quill/dist/quill.min.js:8:27444
S</<.value/<#http://localhost:8080/node_modules/quill/dist/quill.min.js:8:5320
a#http://localhost:8080/node_modules/quill/dist/quill.min.js:7:29623
S</<.value#http://localhost:8080/node_modules/quill/dist/quill.min.js:8:5290
L</<.value#http://localhost:8080/node_modules/quill/dist/quill.min.js:13:4073
x</<.value/<#http://localhost:8080/node_modules/quill/dist/quill.min.js:13:7726
ZoneDelegate.prototype.invokeTask#http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:225:23
NgZone</NgZone.prototype.forkInnerZoneWithAngularBehavior/this.inner<.onInvokeTask#http://localhost:8080/prod/vendor.js:32014:33
ZoneDelegate.prototype.invokeTask#http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:224:23
Zone.prototype.runTask#http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:125:28
ZoneTask/this.invoke#http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:293:28
ErrorHandler</ErrorHandler.prototype.handleError http://localhost:8080/prod/vendor.js:31115:18
PlatformRef_</PlatformRef_.prototype._bootstrapModuleFactoryWithZone/</<.next http://localhost:8080/prod/vendor.js:36067:70
EventEmitter</EventEmitter.prototype.subscribe/schedulerFn< http://localhost:8080/prod/vendor.js:31736:41
SafeSubscriber</SafeSubscriber.prototype.__tryOrUnsub http://localhost:8080/prod/vendor.js:41339:14
SafeSubscriber</SafeSubscriber.prototype.next http://localhost:8080/prod/vendor.js:41288:18
Subscriber</Subscriber.prototype._next http://localhost:8080/prod/vendor.js:41241:10
Subscriber</Subscriber.prototype.next http://localhost:8080/prod/vendor.js:41205:14
Subject</Subject.prototype.next http://localhost:8080/prod/vendor.js:40828:18
EventEmitter</EventEmitter.prototype.emit http://localhost:8080/prod/vendor.js:31722:59
NgZone</NgZone.prototype.triggerError http://localhost:8080/prod/vendor.js:32083:61
NgZone</NgZone.prototype.forkInnerZoneWithAngularBehavior/this.inner<.onHandleError http://localhost:8080/prod/vendor.js:32044:22
ZoneDelegate.prototype.handleError http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:196:19
Zone.prototype.runTask http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:128:25
ZoneTask/this.invoke http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:293:28
Error: [Parchment] Unable to create formula blot
e http://localhost:8080/node_modules/quill/dist/quill.min.js:7:13845
n http://localhost:8080/node_modules/quill/dist/quill.min.js:7:12290
l</e.prototype.insertAt http://localhost:8080/node_modules/quill/dist/quill.min.js:7:25329
j</<.value http://localhost:8080/node_modules/quill/dist/quill.min.js:9:4946
s</e.prototype.insertAt http://localhost:8080/node_modules/quill/dist/quill.min.js:7:5404
s</e.prototype.insertAt http://localhost:8080/node_modules/quill/dist/quill.min.js:7:21442
x</<.value http://localhost:8080/node_modules/quill/dist/quill.min.js:10:5543
q</<.value http://localhost:8080/node_modules/quill/dist/quill.min.js:8:27444
S</<.value/< http://localhost:8080/node_modules/quill/dist/quill.min.js:8:5320
a http://localhost:8080/node_modules/quill/dist/quill.min.js:7:29623
S</<.value http://localhost:8080/node_modules/quill/dist/quill.min.js:8:5290
L</<.value http://localhost:8080/node_modules/quill/dist/quill.min.js:13:4073
x</<.value/< http://localhost:8080/node_modules/quill/dist/quill.min.js:13:7726
ZoneDelegate.prototype.invokeTask http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:225:23
NgZone</NgZone.prototype.forkInnerZoneWithAngularBehavior/this.inner<.onInvokeTask http://localhost:8080/prod/vendor.js:32014:33
ZoneDelegate.prototype.invokeTask http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:224:23
Zone.prototype.runTask http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:125:28
ZoneTask/this.invoke http://localhost:8080/resources/js/libs/angular/zone.0.6.21.js:293:28
index.html
<link rel="stylesheet" type="text/css" href="/node_modules/katex/dist/katex.min.css" />
<script type="text/javascript" src="/node_modules/katex/dist/katex.min.js"></script>
<script src="node_modules/quill/dist/quill.min.js"></script>
Component
import { Component } from '#angular/core';
#Component({
template: `
<p-editor [(ngModel)]="text" [style]="{'height':'150px'}">
<header>
<span class="ql-formats">
<button class="ql-formula"></button>
</span>
</header>
</p-editor>
`
})
export class EmptyDemo {
text: string;
constructor() { }
}
Versions:
Katex 0.6.0,
Quill 1.1.9,
PrimeNG 1.1.3
How can I solve this?

Related

HERE maps - how to get all visible clusters?

I want to get array of currently visible clusters and then get each point data. I create method in React and it seems that method in theme for getClusterPresentation returns all possible clusters for all map zooms. How to get clusters data? This is my code:
const dataPoints = points.map(
point => new H.clustering.DataPoint(point.lat, point.lng, undefined, point),
);
const clusteredDataProvider = new H.clustering.Provider(dataPoints, {
clusteringOptions: {
eps: 32,
minWeight: 2,
},
});
const defaultTheme = clusteredDataProvider.getTheme();
clusteredDataProvider.setTheme({
getClusterPresentation: cluster => {
const clusterMarker = defaultTheme.getClusterPresentation(cluster);
return clusterMarker;
},
getNoisePresentation: noisePoint => {},
});
const layer = new H.map.layer.ObjectLayer(clusteredDataProvider);
map.addLayer(layer);
Please check the below code related to Marker Clustering. And you check same example in our Guide
/**
* Display clustered markers on a map
*
* Note that the maps clustering module https://js.api.here.com/v3/3.1/mapsjs-clustering.js
* must be loaded to use the Clustering
* #param {H.Map} map A HERE Map instance within the application
* #param {Object[]} data Raw data that contains airports' coordinates
*/
function startClustering(map, data) {
// First we need to create an array of DataPoint objects,
// for the ClusterProvider
var dataPoints = data.map(function (item) {
return new H.clustering.DataPoint(item.latitude, item.longitude);
});
// Create a clustering provider with custom options for clusterizing the input
var clusteredDataProvider = new H.clustering.Provider(dataPoints, {
clusteringOptions: {
// Maximum radius of the neighbourhood
eps: 32,
// minimum weight of points required to form a cluster
minWeight: 2
}
});
// Create a layer tha will consume objects from our clustering provider
var clusteringLayer = new H.map.layer.ObjectLayer(clusteredDataProvider);
// To make objects from clustering provder visible,
// we need to add our layer to the map
map.addLayer(clusteringLayer);
}
/**
* Boilerplate map initialization code starts below:
*/
// Step 1: initialize communication with the platform
// In your own code, replace variable window.apikey with your own apikey
var platform = new H.service.Platform({
apikey: window.apikey
});
var defaultLayers = platform.createDefaultLayers();
// Step 2: initialize a map
var map = new H.Map(document.getElementById('map'), defaultLayers.vector.normal.map, {
center: new H.geo.Point(30.789, 33.790),
zoom: 2,
pixelRatio: window.devicePixelRatio || 1
});
// add a resize listener to make sure that the map occupies the whole container
window.addEventListener('resize', () => map.getViewPort().resize());
// Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Step 4: create the default UI component, for displaying bubbles
var ui = H.ui.UI.createDefault(map, defaultLayers);
// Step 5: cluster data about airports's coordinates
// airports variable was injected at the page load
startClustering(map, airports);
#map {
width: 95%;
height: 450px;
background: grey;
}
#panel {
width: 100%;
height: 400px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Marker Clustering</title>
<link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
<link rel="stylesheet" type="text/css" href="demo.css" />
<link rel="stylesheet" type="text/css" href="styles.css" />
<link rel="stylesheet" type="text/css" href="../template.css" />
<script type="text/javascript" src='../test-credentials.js'></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
<script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-clustering.js"></script>
<script type="text/javascript" src="./data/airports.js"></script>
</head>
<body id="markers-on-the-map">
<div class="page-header">
<h1>Marker Clustering</h1>
<p>Cluster multiple markers together to better visualize the data</p>
</div>
<p>This example displays a map showing the distribution of
airports across the world. The locations were obtained by using
the OpenFlights Airport Database.
Instead of adding a marker for each location, the data has been clustered,
and individual airports are only shown at higher zoom levels.</p>
<div id="map"></div>
<h3>Code</h3>
<p>Marker clustering requires the presence of the <code>mapsjs-clustering</code> module of the API.
The <code>H.clustering.Provider</code> class is used to load in data points and prepare them for clustering.
The result is added to the map as an additional layer using the <code>map.addLayer()</code> method.</p>
<script type="text/javascript" src='demo.js'></script>
</body>
</html>

TypeError: window.gtag is not a function

I'm totally puzzled with GTM, I implemented it to my webSite to trigger some events to handle traffic, ect... It's be like 2 days I saw the following error :
Error from the trackerPageView => TypeError: window.gtag is not a function
at _app.js:1
at _app.js:1
at commons.c57c1be722ad069a7405.js:1
at Array.map (<anonymous>)
at Object.emit (commons.c57c1be722ad069a7405.js:1)
at commons.c57c1be722ad069a7405.js:1
I didn't see any doc about this problem so I make a post to centralize information about this problem.
My config is a webApp (nextjs, Reactjs, typeScript, redux), hopefully this will help.
_document.tsx :
import Document, { Head, Main, NextScript } from "next/document";
import { GA_TRACKING_ID } from "../lib/gtag";
import { Fragment } from "react";
export default class MyDocument extends Document {
setGoogleTags() {
return {
__html: `
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','${GA_TRACKING_ID}');
`,
};
}
render() {
return (
<html lang="fr">
<Head>
<Fragment>
<script dangerouslySetInnerHTML={this.setGoogleTags()} />
</Fragment>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link
rel="shortcut icon"
href="***"
crossOrigin="anonymous"
/>
<link
rel="stylesheet"
href="***.css"
crossOrigin="anonymous"
/>
</Head>
<body>
<noscript>
<iframe
src={`https://www.googletagmanager.com/ns.html?id=${GA_TRACKING_ID}`}
height="0"
width="0"
style={{ display: "none", visibility: "hidden" }}
></iframe>
</noscript>
<Main />
<NextScript />
<script
type="text/javascript"
id="hs-script-loader"
async
defer
src="//js.hs-scripts.com/*****.js"
></script>
</body>
</html>
);
}
}
gtg/index.ts:
export const GA_TRACKING_ID = 'GTM-XXXX'
export default function trackPageView(url) {
try {
if (window.gtag)
window.gtag("config", GA_TRACKING_ID, {
page_location: url,
});
} catch (error) {
console.log("Error from the trackerPageView => ", error);
}
}
Solution I found temporary!
So currently my implementation of gtag let me to have firer and trigger detected by GTM, I just set a new trigger to
History modification
and now it's firing my events assigned with this trigger at each history modification. I'm not very confortable with gtag but this enough for me (for now), I'm still annoyed because of the implementation I did. I would like to find the right implementation to clean mine.
The problem clearly come from the SSR because the window variable is become undefined (don't exist in nodeJs) to the error above appear. Still search solution to fix it...
https://github.com/vercel/next.js/discussions/14980
Thx everyone and have a good day :)
You'll want to check for the existence of the window before using window.
For example:
if (typeof window !== 'undefined') {
window.gtag("config", GA_TRACKING_ID, {
page_location: url,
});
}
Also you do not need to wrap your Google Tag Manager script in <Fragment>
Lastly, it looks like gtag is not something globally available by default. You have to set it up yourself according to this document: https://developers.google.com/analytics/devguides/collection/gtagjs
Had the same issue, i used a slightly different version than the other suggestions:
if (typeof window.gtag !== 'undefined')
In my case, I forgot to add #types/gtag.js.
For example,
npm install #types/gtag.js --save-dev
It seems you don't define the gtag in _document.tsx, try to add the script in <Head>. Also, add the script which link to gtm.
<Head>
<script
async
src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
/>
<script
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_TRACKING_ID}', {
page_path: window.location.pathname,
});
`,
}}
/>
</Head>
In my case the problem was I used import Script from "next/script"; instead simple html script. Hope it 'll help to someone.
I have implemented following this article and it works perfectly!
https://www.learnbestcoding.com/post/22/reactjs-using-google-analytics-tag-manager
declare global {
interface Window {
dataLayer: Record<string, any>[];
}
}
React.useEffect(() => {
const analytics = (
w: Window,
d: Document,
s: string,
l: string,
i: string
) => {
(w as any).dataLayer = (window as any).dataLayer || [];
(w as any).dataLayer.push({
"gtm.start": new Date().getTime(),
event: "gtm.js",
});
var dl = l != "dataLayer" ? "&l=" + l : "";
var scr = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
/*
To avoid Multiple installations of google tag manager detected warning
*/
if (!scriptExists(scr)) {
var f = d.getElementsByTagName(s)[0],
j: HTMLScriptElement = d.createElement("script");
j.async = true;
j.src = scr;
f?.parentNode?.insertBefore(j, f);
}
};
const scriptExists = (url: string) => {
var scripts = document.getElementsByTagName("script");
for (var i = scripts.length; i--; ) {
if (scripts[i].src == url) return true;
}
return false;
};
analytics(
window,
document,
"script",
"dataLayer",
process.env.NODE_ENV !== "development" ? `${gaTrackingId}` : "GTM-XXXXXX"
);
}, [gaTrackingId]);

React ES6 class method does not render into html table but outside it. Why?

I want to understand ES6 and are using HTML table to render external React elements. Having trouble rendering this ES6 class into a html table.
I've tried rendering ES6 object from inside the class by returning a string to a HTML table which didn't render so now I render it externally to the class which renders to the bottom outside the table. I am using external CSS for the table and none of the other rendered elements are affected and are rendering to thier cells.
React.js
//PROBLEM: To create an igor skate from an inline skate model.
//START
//CREATE Class Roller_Blades.
//CONSTRTUCT property Name "Inline Skate"
//RETURN SkateType "I am a " Name " designed for mass production."
//END CLASS
class InlineSkate {
constructor(name) {
this.brand = name;
}
present() {
return "I am a " + this.brand + " designed for mass production."
}
}
//This string outside the class will output 'K2 Skate' back into
// InlineSkate.CreateRollerBlade().
var skate = new InlineSkate('K2 Skate');
document.write(skate.present());
ReactDOM.render(React.createElement(InlineSkate, null), document.getElementById('esSixClassExample'));
HTML
<body>
<!--Output-->
<table ID="DoubleBorderedTable">
<tbody>
<tr>
<th>ES6 Class Example</th>
</tr>
<tr>
<td><div id="hello-example"></div></td>
<td><div id="clock-example"></div></td>
<td><div id="es6ClassExample"></div></td>
</tr>
</tbody>
</table>
<!-- Load React. -->
<!-- Note: when deploying, replace "development.js" with
production.min.js". -->
<script src="https://unpkg.com/react#16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js" crossorigin></script>
<!-- Load our React components.-->
<script src="scripts/simple_component.js"></script>
<script src="scripts/Clock.js"></script>
<script src="scripts/ESSixClassExample.js"></script>
</body>
The class function "present" that returns a string ends up rendering outside and below the table and not in the desired last cell of the last row of the table.
ReactDOM.render(React.createElement(InlineSkate, null), document.getElementById('esSixClassExample'))
This is doing nothing. I'd be willing to bet that if you opened your console you'd see an error that says something like, "Cannot call a class as a function".
What's printing the string outside the table are these two lines,
var skate = new InlineSkate('K2 Skate');
document.write(skate.present());
As it is you aren't really using React at all. The first argument of ReactDOM.render() should be either a function component, a class component, or a string designating the type of element to be created.
In order to get the output you want without changing what you're doing so much, you'd need to do something like this,
var skate = new InlineSkate("K2 Skate");
ReactDOM.render(
React.createElement("span", { children: skate.present() }),
document.getElementById("esSixClassExample")
);
What that will do is create a span element, stick it inside your esSixClassExample div, and then run your present function to generate your text and assigning the text node as a child of the span.
This is pretty irregular though, and unless you're just doing this for learning purposes or as part of a class or something, you really ought to be using React components (because why even bother with React otherwise.)
Here is a class component example.
class InlineSkate extends React.Component {
render() {
return React.createElement(React.Fragment, null, "I am a ", this.props.brand, " designed for mass production.");
}
}
ReactDOM.render(React.createElement(InlineSkate, {
brand: "K2 Skate"
}), document.getElementById('classComponent'));
And here is a function component example.
function InlineSkate({ brand }) {
return React.createElement(React.Fragment, null, "I am a ", brand, " designed for mass production.");
}
ReactDOM.render(React.createElement(InlineSkate, {
brand: "K2 Skate"
}), document.getElementById('functionComponent'));

polymer 1.0 .. importing a catalog element with a custom element throws an error

Had created and used my custom polymer element which is a table. Now, I want to use the check box element from their catalog in my table.
However, I keep getting this error when I reference the check box html file in my index page:
DuplicateDefinitionError: a type with name 'dom-module' is already
registered
This is how I have created my custom element:
<!-- Imports polymer -->
<link rel="import" href="polymer/polymer.html">
<script src="underscore-min.js"></script>
<!-- Defines element markup -->
<dom-module id="custom-table" >
<template>
<style>
ul {list-style-type:none; display:block}
ul li {display:inline; float:left; padding:20px; width:1.5em; border-bottom:1px solid #eee}
</style>
<h2>{{title}}</h2>
<table id="dataTable">
<thead id="tableHead"></thead>
<tbody id="tableBody"></tbody>
</table>
</template>
</dom-module>
<!-- Registers custom element -->
<script>
Polymer({
is: 'custom-table',
// Fires when an instance of the element is created
created: function() {
},
// Fires when the local DOM has been fully prepared
ready: function() {
var context= this;
this.pageNo=0;
this.totalPages=0;
// set the default paging size:
if(this.page== null|| this.page==undefined)
this.page=10;
// delegate the change selection handler to the table body
this.$.tableBody.addEventListener("click",function(e){
if(e.target && e.target.nodeName == "INPUT") ;
{
context.changeSelection(e.target);
}
});
},
// Fires when the element was inserted into the document
attached: function() {},
// Fires when the element was removed from the document
detached: function() {},
// Fires when an attribute was added, removed, or updated
attributeChanged: function(name, type) {
alert("changed");
},
loadData: function(columns,data){
this.data = data;
// add the selected property to the values
for(var i=0;i<this.data.length; i++) { this.data[i].Selected = false;}
this.filteredData=this.data;
this.columns = columns;
//initialize the filteredData
this.filteredData=data;
// calculate the total number of pages
this.totalPages= Math.ceil(data.length/this.page);
this.drawTableHeader();
_.defer(this.applyFilters,this);
_.defer(this.drawTableBody,this);
},
drawTableHeader:function(){
var columns = this.columns;
// load the header
var headTr = document.createElement('tr');
//add a blank header for the check box;
var th=document.createElement('th');
headTr.appendChild(th);
for(var i = 0; i<columns.length ;i++)
{
var td=document.createElement('th');
// if the column is sortable then add the event listener for sorting it
if(columns[i].Sortable)
{
td.addEventListener("click",function(){ this.sortBy(columns[i].Title); });
}
td.innerText = columns[i].Title;
headTr.appendChild(td);
}
this.$.tableHead.appendChild(headTr);
},
drawTableBody: function(context){
// this is a defered function
var context = context;
// get the number of items according to the current page number
var pageItems= context.filteredData.slice((context.page*context.pageNo),((context.page*context.pageNo)+context.page));
console.log(pageItems);
// print the page items
for(var i=0; i < pageItems.length; i++)
{
var currItem = pageItems[i];
var tr= document.createElement("tr");
// add the check box first
var checkbox= document.createElement("input");
checkbox.type="checkbox";
checkbox.checked=pageItems[i].Selected;
var ItemId = currItem.Id;
checkbox.setAttribute("data-ItemId",ItemId-1);
var td=document.createElement('td');
td.appendChild(checkbox);
tr.appendChild(td);
// for every column specified add a column to it
for(var j = 0; j< context.columns.length; j++)
{
var td=document.createElement("td");
td.innerText= pageItems[i][context.columns[j].Title];
tr.appendChild(td);
}
//append the row to the table;
context.$.tableBody.appendChild(tr);
} // end for i
},
applyFilters:function(context){
if(context.filter)
{
alert("filterApplied");
}
},
changeSelection:function(checkbox){
var ItemId = checkbox.getAttribute("data-ItemId");
this.data[ItemId].Selected= checkbox.checked;
console.log(this.data[ItemId]);
},
properties:{
title :String,
columns:Array,
data:Array,
page:Number,
filters:Object,
Selectable:Boolean
}
});
</script>
and here is what my index page looks like:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title><my-repo></title>
<!-- Imports polyfill -->
<script src="webcomponents-lite.min.js"></script>
<!-- Imports custom element -->
<link rel="import" href="my-element.html">
<link rel="import" href="bower_components/paper-checkbox/paper-checkbox.html">
</head>
<body unresolved>
<!-- Runs custom element -->
<custom-table title="This is data table"></custom-table>
<script>
document.addEventListener("WebComponentsReady",function(){
var data = [{'Id':1,'firstName':'aman',age:25},{'Id':2,'firstName':'gupta',age:25}];
var cols = [{Title:'firstName',Sortable:true},{Title:'age',Sortable:false}];
var a = document.querySelector('my-element');
a.loadData(cols,data);
});
</script>
</body>
</html>
I've just started out with polymer and I'm not quite sure what's going on here..
Thank you in advance :)
I got what the problem is..
My custom element was referencing a different Polymer.html file.
Silly me :D
I'm using Polymer Starter Kit Yeoman generator on Windows and I had the same problem:
Error: DuplicateDefinitionError: a type with name 'dom-module' is already registered
This error is triggered in Firefox console. Chrome works fine.
The components created with the generator (example: yo polymer:el my-element) have this polymer.html import:
<link rel="import" href="..\..\bower_components/polymer/polymer.html">
The base path is described with "backslash".
In some custom polymer elements I created by myself, I imported polymer.html with:
<link rel="import" href="../../bower_components/polymer/polymer.html">
And I think this lead to a duplication of some kind. To solve the problem, I just changed all automatically created imports, using only forward slashes /.
Hope this helps someone.

jQuery mobile calendar with 3-state day colours

I am looking at creating an event and reservation system.
I found the Stack Overflow question jQuery - Mobile date picker control which shows jquery-mobile-datebox and jQuery-Mobile-Themed-DatePicker.
I want to display a calendar where certain dates I get from the server are
available
not available
reserved
When a reserved or available date is touched, I want to show times - there can be more than one time per day. The user can then click on a time to reserve it which would hit off an Ajax request.
jQuery UI datepicker, for example, has
onSelect: function(date, inst) {
From what I can see in the above pickers, what I need is not readily available. Before I start hacking them myself:
Which one would lend itself best to what I want?
Are there perhaps better ones out there that already serve my needs?
UPDATE:
Firebug gave me
<div class="ui-datebox-griddate ui-corner-all ui-btn-up-e" data-date="25" data-theme="e">25</div>
where ui-btn-up-e can be changed from a - e.
Now I need to find out if data-theme also needs to be changed
$('.ui-datebox-griddate').click(function () {
alert($(this).attr("class"));
}
What is the nicest way to toggle through three of the classes and save the state each time?
$('.ui-datebox-griddate').toggle(
function () {
$(this).????? // change ui-btn-up-? to ui-btn-up-a
$.get(...)
},
function () {
$(this).????? // change ui-btn-up-a to ui-btn-up-b
$.get(...)
},
function () {
$(this).????? // change ui-btn-up-b to ui-btn-up-c
$.get(...)
}
);
UPDATE: NOTE: When I click, the calendar change the date, reloading the calendar completely. Perhaps I need to stop that :(
What is the nicest way to toggle through three of the classes and save the state each time?
Something like:
$('.ui-datebox-griddate').click(function (e) {
var $this = $(this);
var cycle = ["ui-btn-up-a", "ui-btn-up-b", "ui-btn-up-c"];
if (typeof $this.data("ui-btn-cycle") == "undefined" ) {
this.className = this.className.replace(/ui-btn-up-./, cycle[0]);
$this.data("ui-btn-cycle", cycle[0]);
}
for (var i=0; i<cycle.length; i++) {
if ( $this.hasClass(cycle[i]) ) {
$this.removeClass(cycle[i]).addClass(cycle[i % cycle.length]);
$this.data("ui-btn-cycle", [i % cycle.length]);
break;
}
}
$.get( ... );
e.preventDefault() // stop default click behaviour
});
This can cycle though an arbitrary amount of classes. The current state would be available through calling .data("ui-btn-cycle") on the respective element.
This is even nicer:
$('.ui-datebox-griddate')
.each(function () {
var cycle = ["ui-btn-up-a", "ui-btn-up-b", "ui-btn-up-c"];
$(this).data("ui-btn-cycle", cycle);
this.className = this.className.replace(/ui-btn-up-./, cycle[0]);
})
.click(function (e) {
var cycle = $(this).data("ui-btn-cycle");
$(this).removeClass(cycle[0]).addClass(cycle[1]);
cycle.push(cycle.shift());
e.preventDefault();
});
The current state would always be .data("ui-btn-cycle")[0] on the respective element. See it working here: http://jsfiddle.net/Tomalak/mAH4n/
Based on what J.T.Sage said I thought I would have a play with jQuery Mobile Calendar. I think I have something which could potentially be extended to fulfil your requirements. I am not sure to what extent multi-colour themeing would be possible (without extensive modifications).
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQueryMobile - DateBox Demos</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.css" />
<link type="text/css" href="http://dev.jtsage.com/cdn/datebox/latest/jquery.mobile.datebox.min.css" rel="stylesheet" />
<!-- NOTE: Script load order is significant! -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script type="text/javascript">
$( document ).bind( "mobileinit", function(){ $.mobile.page.prototype.options.degradeInputs.date = 'text'; });
</script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script>
<script type="text/javascript" src="http://dev.jtsage.com/cdn/datebox/latest/jquery.mobile.datebox.min.js"></script>
<script type="text/javascript">
$('#page').live('pagecreate', function(event) {
$('#mydate').bind('change', function () {
alert($(this).val());
});
});
</script>
</head>
<body>
<div id="page" data-role="page">
<div data-role="content">
<input name="mydate" id="mydate" type="date" data-role="datebox" data-options='{"mode": "calbox", "calHighToday": false, "calHighPicked": false, "useInline": true, "useInlineHideInput": true, "highDates": ["2011-06-25", "2011-06-27", "2011-07-04"]}'></input>
</div>
</div>
</html>
UPDATE
I suppose the highDates mechanism could be bypassed completely and the individual days uniquely targeted. The plugin maintains a JavaScript Date object of the last date selected (or today if nothing has been selected) - so it should be possible to get the current month and iterate through all your matching data updating the matching days in the current month as appropriate (e.g. replacing the setColours method below with something that is data/state aware).
<script type="text/javascript">
$('#page').live('pagecreate', function(event) {
$('#mydate').bind('change', function () {
//alert($(this).val());
alert($('#mydate').data('datebox').theDate);
});
setColours();
$('#mydate').bind('datebox', function (e, pressed) {
setColours();
});
$('.ui-datebox-gridplus, .ui-datebox-gridminus').bind('vclick', function(){
// To handle changing months
setColours();
//alert($('#mydate').data('datebox').theDate);
});
function setColours(){
$('div.ui-datebox-griddate[data-date=25][data-theme]').css({"background-color":"red", "background-image":"none", "color" : "white"});
$('div.ui-datebox-griddate[data-date=26][data-theme]').css({"background-color":"green", "background-image":"none", "color" : "white"});
$('div.ui-datebox-griddate[data-date=27][data-theme]').css({"background-color":"blue", "background-image":"none", "color" : "white"});
}
});
</script>

Resources