Ractive recursive partials with couter - recursion

I had some problem when I used recursive partials. I tried to create comments which every one can comment again, like this:
comment (depth 0)
comment (depth 1)
comment (depth 2)
I want to add some special classes for different depth of comments
{{#messages}}
{>message}
{{/messages}}
<!-- {{>message}} -->
<div class="{{getClasses()}}"">{{text}}</div>
{{incrDepth()}}
{{#comments}}
{{>message}}
{{/comments}}
{{decrDepth()}}
<!-- {{/message}} -->
This is additional function which I use
{
data: {
incrDepth: function () {
this.depth++;
},
decrDepth: function () {
this.depth--;
},
getClasses: function () {
return 'depth' + this.depth;
}
}
}
So, before every comments I increase depth and after comments I decrease it. But unfortunately all my invokes of getClasses() return 'depth0' and I can't understand why.

It helps if you think of templates as being read-only - rather than 'executing' the template from top to bottom, Ractive constructs a virtual DOM from the template, and updates nodes within it whenever they need to change. For that reason, there's no guarantee about when a given function will be called.
So you should avoid functions with 'side-effects' - they should be for retrieving data, never setting it.
But a recursive structure is definitely possible - you need to use inline components. A component is a nested Ractive instance that manages its own data, and it's easy to set a depth property to 'whatever the parent depth is, plus one' - try running the code snippet below to see it in action.
Ractive.components.comment = Ractive.extend({
template: '#comment',
data: { depth: 0 } // default
});
var ractive = new Ractive({
el: 'main',
template: '#template',
data: {
comments: [
{
author: 'alice',
content: 'FIRST!'
},
{
author: 'bob',
content: 'first!!1!',
children: [
{
author: 'bob',
content: 'argh alice beat me',
children: [
{
author: 'alice',
content: 'haha'
},
{
author: 'charles',
content: 'you snooze you lose'
}
]
}
]
},
{
author: 'larry_34xj',
content: 'Thank you for this article, it is very interesting. Please visit my blog at http://pills4u.com'
},
{
author: 'dawn',
content: 'This article is terrible. I don\'t know where to begin',
children: [
{
author: 'bob',
content: 'do you have nothing better to do than write snarky comments on blog posts?',
children: [
{
author: 'dawn',
content: 'Do you have nothing better to do than write "first"? loser',
children: [
{
author: 'bob',
content: 'touché'
},
{
author: 'alice',
content: 'haha pwned'
}
]
}
]
}
]
}
]
}
});
body { font-family: 'Helvetica Neue', arial, sans-serif; font-weight: 200; color: #353535; } h1 { font-weight: 200; } p { margin: 0.5em 0; }
.comment {
padding: 0.5em;
border-top: 1px solid #eee;
}
.comment .comment {
padding-left: 2em;
}
.depth-1 {
color: #555;
}
.depth-2 {
color: #999;
}
<script src="http://cdn.ractivejs.org/latest/ractive.js"></script>
<main></main>
<script id='template' type='text/ractive'>
<h1><a href='http://ifyoulikeitsomuchwhydontyougolivethere.com/' target='_blank'>spEak You're bRanes</a></h1>
{{#each comments}}
<comment comment='{{this}}'/>
{{/each}}
</script>
<script id='comment' type='text/ractive'>
<article class='comment depth-{{depth}}'>
<p><strong>{{comment.author}}</strong> wrote:</p>
<p>{{comment.content}}</p>
{{#each comment.children}}
<comment comment='{{this}}' depth='{{depth + 1}}'/>
{{/each}}
</article>
</script>

Related

vue-simple-calendar "classes" item properties not working

I am using vue-simple-calendar as npm calendar package for my vuejs project and I want to implement dynamic classes for each event items. Ex. background-color, etc. But the classes property is not working.
Reference: https://github.com/richardtallent/vue-simple-calendar#calendar-item-properties
Live demo: https://tallent.us/vue-simple-calendar/ (seems to be ok in demo)
Demo (App.vue file): https://github.com/richardtallent/vue-simple-calendar-sample/blob/main/src/App.vue (classes property is implemented)
style property is working:
var app = new Vue({
el: '#app',
data: function() {
return {
showDate: new Date('10/15/2018'),
events: [
{
startDate: '2018-10-06',
endDate: '2018-10-13',
title: 'Sample event 2',
style: 'background-color: red'
}
]
}
},
component: {
"calendar-view": window.CalendarView,
},
methods: {
setShowDate(d) {
this.showDate = d;
},
onClickEvent() { alert('event clicked') }
}
})
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
color: #2c3e50;
height: 67vh;
width: 90vw;
margin-left: auto;
margin-right: auto;
}
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js" ></script>
<script src="https://unpkg.com/vue-simple-calendar#4.1.0/dist/CalendarView.umd.js" ></script>
<div id="app">
<h1>My Calendar</h1>
<calendar-view
:show-date="showDate" :events="events" display-period-uom="month" :display-period-count="4"
class="theme-default holiday-us-traditional holiday-us-official"
#click-event="onClickEvent">
<calendar-view-header
slot="header"
slot-scope="t"
:header-props="t.headerProps"
#input="setShowDate" />
</calendar-view>
</div>
on the other side, classes property is not working:
var app = new Vue({
el: '#app',
data: function() {
return {
showDate: new Date('10/15/2018'),
events: [
{
startDate: '2018-10-06',
endDate: '2018-10-13',
title: 'Sample event 2',
classes: 'bg-red'
}
]
}
},
component: {
"calendar-view": window.CalendarView,
},
methods: {
setShowDate(d) {
this.showDate = d;
},
onClickEvent() { alert('event clicked') }
}
})
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
color: #2c3e50;
height: 67vh;
width: 90vw;
margin-left: auto;
margin-right: auto;
}
.bg-red {
background-color: red
}
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js" ></script>
<script src="https://unpkg.com/vue-simple-calendar#4.1.0/dist/CalendarView.umd.js" ></script>
<div id="app">
<h1>My Calendar</h1>
<calendar-view
:show-date="showDate" :events="events" display-period-uom="month" :display-period-count="4"
class="theme-default holiday-us-traditional holiday-us-official"
#click-event="onClickEvent">
<calendar-view-header
slot="header"
slot-scope="t"
:header-props="t.headerProps"
#input="setShowDate" />
</calendar-view>
</div>
This was a bug in the documentation, now fixed! The classes property is actually expected to be an array of strings, not a single string. *E.g.:
classes: ['bg-red']

ability to add event location to FullCalendarIO

What to know if it is possible to add locations to events in the fullcalendar.io. as nothing in the demo for meeting locations or in documentation?
The document of Event Object mentions that you can include your own fields in the Event Object. FullCalendar will not modify or delete them but also won't render them.
So you can add locations to your events, but you have to find your own way to render them.
You can find the document of eventRender here.
And here is an example for showing the event location:
$(function() {
$('#calendar').fullCalendar({
defaultView: 'month',
defaultDate: '2018-10-07',
header: {
left: 'prev,next',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
events: [{
title: 'Meeting',
start: '2018-10-12T14:30:00',
location: 'Conference Room'
}],
eventRender: function(event, element) {
element.text(element.text() + ' ' + event.location)
}
});
});
html,
body {
margin: 0;
padding: 0;
font-family: "Lucida Grande", Helvetica, Arial, Verdana, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 900px;
margin: 40px auto;
}
<link href="https://fullcalendar.io/releases/fullcalendar/3.9.0/fullcalendar.min.css" rel="stylesheet" />
<script src="https://fullcalendar.io/releases/fullcalendar/3.9.0/lib/jquery.min.js"></script>
<script src="https://fullcalendar.io/releases/fullcalendar/3.9.0/lib/moment.min.js"></script>
<script src="https://fullcalendar.io/releases/fullcalendar/3.9.0/fullcalendar.min.js"></script>
<div id='calendar'></div>
If you want to add fields that aren't included in what FullCalendar will render you can check the doc https://fullcalendar.io/docs/v4/eventRender first of all.
In my case I've done this using the eventRender function to add the location after the already existing text, ofc you need to add the additional fields to the extendedProps:
eventRender: function(info) {
info.el.innerText = info.el.outerText + ' ' + info.event._def.extendedProps.location;
}

Animate a quizz app with AngularJS

I had done one quiz application, But i want to add some animations
like fadein/fade-out, when click the prev/next button. Can any one
help me do the same. something need to change the css something need to change the CSS something need to change the css something need to change the css?
* {}
body {}
.question {
width: 70%;
margin: 0 auto;
height: auto;
display: block;
background: #eeeeee;
}
.question h1 {
text-align: center;
padding-top: 30px;
color: #666666;
}
.question h2 {
width: 100%;
font-size: 22px;
color: #0c1e5c;
padding: 1% 3% 0% 3%;
}
.question ul:nth-child(odd) {
background: #d0dff6;
width: 30%;
padding: 8px;
margin: 1% 9%;
display: inline-block;
color: #0c1e5c;
}
.question ul:nth-child(even) {
background: #d0dff6;
width: 30%;
padding: 8px;
margin: 1% 9%;
display: inline-block;
color: #0c1e5c;
}
.button {
text-align: center;
margin: 1% 0;
}
.btn {
background: #8bf8a7;
padding: 5px;
}
<html ng-app="quiz">
<head>
<meta charset="utf-8">
<title>Basic Quiz</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body ng-controller="quizCtrl">
<div class="question">
<h1>QUIZ APPLICATION</h1>
<h2>{{questions.question}}</h2>
<ul ng-repeat="option in questions.options">
<li style="list-style:none">
<input type="{{buttonType}}">{{option.text}}</li>
</ul>
</div>
<div class="button">
<input type="button" value="previous" class="btn" ng-show="isPrevious" ng-click="previousQuestion()">
<input type="button" value="next" class="btn" ng-show="isNext" ng-click="nextQuestion()">
</div>
</body>
<script>
var app = angular.module("quiz", [])
app.controller("quizCtrl", function($scope) {
$scope.data = [{
question: "1)Which of the following selector matches a element based on its id?",
type: "single",
options: [{
text: "The Id Selector"
},
{
text: "The Universal Selector"
},
{
text: "The Descendant Selector"
},
{
text: "The Class Selector"
}
]
},
{
question: "2)Which of the following defines a measurement as a percentage relative to another value, typically an enclosing element?",
type: "multiple",
options: [{
text: "%"
},
{
text: "cm"
},
{
text: "percentage"
},
{
text: "ex"
}
]
},
{
question: "3)Which of the following property is used to set the background color of an element?",
type: "single",
options: [{
text: "background-color"
},
{
text: "background-image"
},
{
text: "background-repeat"
},
{
text: "background-position"
}
]
},
{
question: "4)Which of the following is a true about CSS style overriding?",
type: "multiple",
options: [{
text: "Any inline style sheet takes highest priority. So, it will override any rule defined in tags or rules defined in any external style sheet file."
},
{
text: "Any rule defined in tags will override rules defined in any external style sheet file."
},
{
text: "Any rule defined in external style sheet file takes lowest priority, and rules defined in this file will be applied only when above two rules are not applicable."
}
]
}
];
$scope.index = 0;
$scope.questions = $scope.data[$scope.index];
$scope.buttonType = $scope.questions.type == 'single' ? 'radio' : 'checkbox';
$scope.isPrevious = false;
$scope.isNext = true;
$scope.nextQuestion = function() {
if ($scope.index < 3) {
$scope.index = $scope.index + 1;
$scope.questions = $scope.data[$scope.index];
$scope.buttonType = $scope.questions.type == 'single' ? 'radio' : 'checkbox';
$scope.isPrevious = true;
if ($scope.index == 3) {
$scope.isNext = false;
}
} else {
// disble next botton logic
$scope.isNext = false;
}
}
$scope.previousQuestion = function() {
if ($scope.index > 0) {
$scope.index = $scope.index - 1;
$scope.questions = $scope.data[$scope.index];
$scope.buttonType = $scope.questions.type == 'single' ? 'radio' : 'checkbox';
$scope.isNext = true;
if ($scope.index == 0) {
$scope.isPrevious = false;
}
} else {
// disble next botton logic
$scope.isPrevious = false;
}
}
});
</script>
</html>
Check out ng-animate, basically what it does is it adds classes that you can style accordingly on showing dom and on hiding dom, like this:
/* The starting CSS styles for the enter animation */
.fade.ng-enter {
transition:0.5s linear all;
opacity:0;
}
/* The finishing CSS styles for the enter animation */
.fade.ng-enter.ng-enter-active {
opacity:1;
}
And to use that functionality you would have to use ng-repeat in your html, something like this:
<div ng-repeat="item in data" ng-if="index === $index">
//Your question html here
</div>
Where data and index are $scope.data and $scope.index.
That would be the angular way of doing things.
However I see that you are using the same div, only changing scope data, that would require you to set
transition: 1s all ease;
On the question class, and then to do something like this in javascript:
angular.element('.question').css('opacity', 0);
$timeout(function() {
// change question..
angular.element('.question').css('opacity', 1);
}, 1000);

How to put X inside textfield to clear text in extjs

I want to implement an X button inside a textfield (x on right side of textfield) to clear entered texts. I have seen many extjs application that has this feature. How do I go about doing that? Any suggestion or comments would be really appreciated...
THanks
it looks something like this...
You have to use a Ext.form.field.Trigger. Here is a example for that
Ext.define('Ext.ux.CustomTrigger', {
extend: 'Ext.form.field.Trigger',
alias: 'widget.customtrigger',
initComponent: function () {
var me = this;
me.triggerCls = 'x-form-clear-trigger'; // native ExtJS class & icon
me.callParent(arguments);
},
// override onTriggerClick
onTriggerClick: function() {
this.setRawValue('');
}
});
Ext.create('Ext.form.FormPanel', {
title: 'Form with TriggerField',
bodyPadding: 5,
width: 350,
renderTo: Ext.getBody(),
items:[{
xtype: 'customtrigger',
fieldLabel: 'Sample Trigger',
emptyText: 'click the trigger'
}]
});
For ease of testing, here is a JSFiddle
This is what works for me with the CSS:
CSS
.x-form-clear {
background-image: url('../../resources/themes/images/default/form/clear-trigger.gif');
background-position: 0 0;
width: 17px;
height: 22px;
border-bottom: 1px solid #b5b8c8;
cursor: pointer;
cursor: hand;
overflow: hidden;
}
.x-form-clear-over {
background-position: -17px 0;
border-bottom-color: #7eadd9;
}
.x-form-clear-click {
background-position: -68px 0;
border-bottom-color: #737b8c;
}
Class
Ext.define('Ext.ux.form.field.Clear', {
extend: 'Ext.form.field.Trigger',
alias: 'widget.clearfield',
triggerBaseCls: 'x-form-clear',
onTriggerClick: function() {
this.setValue();
}
});
Usage
Ext.create('Ext.container.Container', {
renderTo: Ext.getBody(),
items: [
Ext.create('Ext.ux.form.field.Clear', {
fieldLabel: 'Clear Field',
cls: 'clear-trigger'
})
]
})
Or use this 'clearbutton' plugin: http://www.eekboom.de/ClearButton.html
I like it because it's just a plugin, one line, instead of requiring a custom subclass.
Also, it can be used on all kinds of fields, not just on a textfield.
You can use the Ext.form.field.Text with triggers in Extjs 5.0 and later, no need to define a new type.
var textfield = Ext.create('Ext.form.field.Text', {
triggers: {
clear: {
cls: 'x-form-clear-trigger',
handler: function () {
this.setValue('');
}
}
}
});
The scope of the trigger's handler is the Ext.form.field.Text component.
You can have multiple triggers, and can also use MVVM model. For example:
var textfield = Ext.create('Ext.form.field.Text', {
triggers: {
clear: {
cls: 'x-form-clear-trigger',
handler: function () {
this.setValue('');
}
},
search: {
cls: 'x-form-search-trigger',
handler: 'onSearch'
}
}
});
The search trigger uses a handler function, i.e. onSearch, that is defined in the controller of the component that has the Ext.form.field.Text object.
In ExtJS 6+, you can also just add the following 2 configs on your Ext.form.field.Text and show/hide the trigger with the built-in change listener
triggers: {
clearText: {
cls: 'clear-text-trigger-icon',
handler: function() {
this.setValue('');
}
}
},
listeners: {
change: function(textField) {
if (textField.getValue()) {
textField.setHideTrigger(false);
} else {
textField.setHideTrigger(true);
}
}
}

Setting up line-height via TinyMCE

Is there a way to give user possibility to easily changing line-height attribute of paragraph in tinyMCE editor? Something like its native "Font size" or "Format" <select> or anything else. I know I can use "edit CSS" functionality and set it up there. I'm looking for something more user-friendly.
I can't find it anywhere.
I found this PlugIn for TinyMCE version 4.1.5 (2014-09-09)
https://github.com/castler/tinymce-line-height-plugin
Setting up like this:
tinymce.init({
plugins: 'lineheight',
toolbar: 'lineheightselect'
});
Also you could configure the different heights like that:
tinymce.init({
lineheight_formats: "8pt 9pt 10pt 11pt 12pt 14pt 16pt 18pt 20pt 22pt 24pt 26pt 36pt",
});
I tested this and it works great.
As per my comment,
Someone else was experiencing an issue similar to yours and a member of the TinyMCE forums provided a solution:
http://www.tinymce.com/forum/viewtopic.php?id=28774
With TinyMCE 4 you can use "style_formats" option
http://www.tinymce.com/wiki.php/Configuration:style_formats
I have found a good way for adding custom line-height to tinymce but this is a trick.
I am using tinymce v5 and with these codes i can use line height with a nice select option.
you have to add these lines to init codes of tiny mce:
tinymce.init({
selector: 'textarea',
height: 500,
plugins: 'table wordcount',
toolbar: ' styleselect ',
content_css: [
'//fonts.googleapis.com/css?family=Lato:300,300i,400,400i',
'//www.tiny.cloud/css/codepen.min.css'
],
toolbar: 'styleselect'
content_style: '.lineheight20px { line-height: 20px; }' +
'.lineheight22px { line-height: 22px; }' +
'.lineheight24px { line-height: 24px; }' +
'.lineheight26px { line-height: 26px; }' +
'.lineheight28px { line-height: 28px; }' +
'.lineheight30px { line-height: 30px; }' +
'.lineheight32px { line-height: 32px; }' +
'.lineheight34px { line-height: 34px; }' +
'.lineheight36px { line-height: 36px; }' +
'.lineheight38px { line-height: 38px; }' +
'.lineheight40px { line-height: 40px; }' +
'.tablerow1 { background-color: #D3D3D3; }',
formats: {
lineheight20px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight20px' },
lineheight22px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight22px' },
lineheight24px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight24px' },
lineheight26px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight26px' },
lineheight28px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight20px' },
lineheight30px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight30px' },
lineheight32px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight32px' },
lineheight34px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight34px' },
lineheight36px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight36px' },
lineheight38px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight38px' },
lineheight40px: { selector: 'span,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'lineheight40px' }
},
style_formats: [
{ title: 'lineheight20px',format: 'lineheight20px' },
{ title: 'lineheight22px', format: 'lineheight22px' },
{ title: 'lineheight24px', format: 'lineheight24px' },
{ title: 'lineheight26px', format: 'lineheight26px' },
{ title: 'lineheight28px', format: 'lineheight28px' },
{ title: 'lineheight30px', format: 'lineheight30px' },
{ title: 'lineheight32px', format: 'lineheight32px' },
{ title: 'lineheight34px', format: 'lineheight34px' },
{ title: 'lineheight36px', format: 'lineheight36px' },
{ title: 'lineheight38px', format: 'lineheight38px' },
{ title: 'lineheight40px', format: 'lineheight40px' }
]
});
and at the end i have to say you need to find a "paragraph" word in the file of tinymce/themes/silver/theme.min.js and change it to "line-height" if you want to see the line-height name instead of paragraph name.
this word is in line of 290855 of that file.
and this job is called custom format in tinymce that if you want to find it check this link:
https://www.tiny.cloud/docs/demo/format-custom/
and I have to say you need to add this css codes to your css file:
.lineheight22px{
line-height: 22px;
}
.lineheight24px{
line-height: 24px;
}
.lineheight26px{
line-height: 26px;
}
.lineheight28px{
line-height: 28px;
}
.lineheight30px{
line-height: 30px;
}
.lineheight32px{
line-height: 32px;
}
.lineheight34px{
line-height: 34px;
}
.lineheight36px{
line-height: 36px;
}
.lineheight38px{
line-height: 38px;
}
.lineheight40px{
line-height: 40px;
}
Indeed, TinyMCE doesn't have line-height control as it has for font names or font sizes, but you can easily add it with the style_formats. I used this config:
// custom formatting is under Format > formats, so make sure it's in your menu (it is, by default)
const editorOptions = {
// Notice that it overrides Format > formats
style_formats: [
{
title: 'Line height',
items: [
{
title: 'Default',
inline: 'span',
// `inline-block` because CSS `line-height` doesn't affect multiline `span`
styles: { 'line-height': 'normal', display: 'inline-block' }
},
{
title: '40px',
inline: 'span',
styles: { 'line-height': '40px', display: 'inline-block' }
},
// add as more as you need
]
},
// ...
]
}
Working example on codepen
TinyMCE style_formats doc

Resources