I want to access the internal widgets but it gives me an error, that I can't index a nil value.
My widget:
local previewWidget = wibox()
previewWidget:setup {
widget = wibox.widget {
{
widget = wibox.widget {
{
widget = awful.widget.clienticon,
client = "",
id = "clientIcon"
},
{
widget = wibox.widget.textbox,
id = "titleText"
},
nil
},
layout = wibox.layout.align.horizontal,
id = "titleBox"
},
{
widget = wibox.widget.imagebox,
id = "clientImage"
},
nil
},
id = "previewBox",
layout = wibox.layout.align.vertical,
border_width = 10,
border_color = "FF0000",
}
This command doesn't give error:
local previewBox = previewWidget:get_children_by_id("previewBox")[1]
But this does:
local titleBox = previewWidget:get_children_by_id("titleBox")[1]
local clientIcon = previewWidget:get_children_by_id("clientIcon")[1]
What am I doing wrong here?
local previewWidget = wibox.widget {
{
{
widget = awful.widget.clienticon,
client = "",
id = "clientIcon"
},
{
widget = wibox.widget.textbox,
id = "titleText"
},
nil,
layout = wibox.layout.align.horizontal,
id = "titleBox"
},
{
widget = wibox.widget.imagebox,
id = "clientImage"
},
nil,
layout = wibox.layout.align.vertical,
id = "previewBox",
}
I incorrectly used the layout:
All 3 widgets needs to be where the layout is called
local some_widget = wibox.widget {
{ widget nr.1 },
{ widget nr.2 },
{ widget nr.3 },
layout = wibox.layout.align.vertical
}
P.S. it's enough to declare a layout without a widget
Related
The goal was i aiming to is to change identifier from id of entity to JWT token that user has attached at specific path.
#ApiResource(
itemOperations = {
"get" ={
"security" = "is_granted('VIEW',object)",
"normalization_context" = {"groups" = {"read"}}
},
"put" = {
"security" = "is_granted('WRITE',object)",
"normalization_context" = {"groups" = {"get"}},
"denormalization_context" = {"groups" = {"put"}}
},
"api_users_cart_subresource" = {
"method" = "GET",
"path" = "/users/{id}/carts",
"security" = "is_granted('VIEW',object)",
"normalization_context" = {"groups" = {"user:cart"}}
}
},
collectionOperations = {
"post" = {
"denormalization_context" = {"groups" = {"post"}},
"normalization_context" = {"groups" = {"get"}}
},
"get" = {
"access_control" = "is_granted('ROLE_ADMIN')",
"normalization_context" = {"groups" = {"admin:read"}}
}
}
)
is it possible to change the path to /users/carts and return normalized data that belong to the user base from their token?
ps. sorry for my grammar
I have a word press website in which i am planning to show the drift chat window for a particular page only but the issue with the code is when i put the drift chat code in the header.php then it shows in the entire website at the footer. But my objective is to display that chat widget in a particular page not the entire site.
In header.php i placed this code.
<!-- Start of Async Drift Code -->
<script>
"use strict";
!function() {
var t = window.driftt = window.drift = window.driftt || [];
if (!t.init) {
if (t.invoked) return void (window.console && console.error && console.error("Drift snippet included twice."));
t.invoked = !0, t.methods = [ "identify", "config", "track", "reset", "debug", "show", "ping", "page", "hide", "off", "on" ],
t.factory = function(e) {
return function() {
var n = Array.prototype.slice.call(arguments);
return n.unshift(e), t.push(n), t;
};
}, t.methods.forEach(function(e) {
t[e] = t.factory(e);
}), t.load = function(t) {
var e = 3e5, n = Math.ceil(new Date() / e) * e, o = document.createElement("script");
o.type = "text/javascript", o.async = !0, o.crossorigin = "anonymous", o.src = "https://js.driftt.com/include/" + n + "/" + t + ".js";
var i = document.getElementsByTagName("script")[0];
i.parentNode.insertBefore(o, i);
};
}
}();
drift.SNIPPET_VERSION = '0.3.1';
drift.load('963auir3rcg6');
</script>
<!-- End of Async Drift Code -->
How can i achieve it?
Any suggestions on it?
Replace this code in header.php
<?php
if(is_page(2)){
?>
<!-- Start of Async Drift Code -->
<script>
"use strict";
!function() {
var t = window.driftt = window.drift = window.driftt || [];
if (!t.init) {
if (t.invoked) return void (window.console && console.error && console.error("Drift snippet included twice."));
t.invoked = !0, t.methods = [ "identify", "config", "track", "reset", "debug", "show", "ping", "page", "hide", "off", "on" ],
t.factory = function(e) {
return function() {
var n = Array.prototype.slice.call(arguments);
return n.unshift(e), t.push(n), t;
};
}, t.methods.forEach(function(e) {
t[e] = t.factory(e);
}), t.load = function(t) {
var e = 3e5, n = Math.ceil(new Date() / e) * e, o = document.createElement("script");
o.type = "text/javascript", o.async = !0, o.crossorigin = "anonymous", o.src = "https://js.driftt.com/include/" + n + "/" + t + ".js";
var i = document.getElementsByTagName("script")[0];
i.parentNode.insertBefore(o, i);
};
}
}();
drift.SNIPPET_VERSION = '0.3.1';
drift.load('963auir3rcg6');
</script>
<!-- End of Async Drift Code -->
<?php } ?>
After upgrading Episerver to version 11.5, the TinyMCE feature of being able to set custom names for menu items in a drop down is no longer working.
The special custom CSS attribute called EditMenuName is not working I guess. those menu items only showing particular CSS class names. not the names which are provided as "EditMenuName" attributes.
How do I get this feature working again?
There is no support for this. What you can do instead is to add these items to the style_formats, please see https://www.tinymce.com/docs/configure/content-formatting/#style_formats. More information on how you can customize the editor https://world.episerver.com/documentation/developer-guides/CMS/add-ons/customizing-the-tinymce-editor-v2/.
Here's an example configuration:
config
.Default()
.Schema(TinyMceSchema.Html5Strict)
.ContentCss("/gui/css/base.css")
.AddPlugin("link table paste code contextmenu")
.Toolbar(
"styleselect undo redo pastetext removeformat searchreplace code fullscreen",
"bold italic numlist bullist outdent indent table epi-link unlink image epi-image-editor epi-personalized-content")
.StyleFormats(
new { title = "Paragraph", format = "p" },
new { title = "Header 2", format = "h2" },
new { title = "Header 3", format = "h3" },
new { title = "Header 4", format = "h4" },
new
{
title = "Inline",
icon = "forecolor",
items = new[]
{
new { title = "Strikethrough", format = "strikethrough", icon = "strikethrough" },
new { title = "Superscript", format = "superscript", icon = "superscript" },
new { title = "Subscript", format = "subscript", icon = "subscript" },
new { title = "code", format = "code", icon = "code" }
}
},
new
{
title = "Blocks",
icon = "template",
items = new[]
{
new { title = "Blockquote", format = "blockquote" },
new { title = "Preformatted", format = "pre" },
}
},
new
{
title = "Images",
icon = "image",
items = new[]
{
new { title = "Left", selector = "img", classes = "left", icon = "alignleft" },
new { title = "Right", selector = "img", classes = "right", icon = "alignright" },
new { title = "Full-width", selector = "img", classes = "fullwidth", icon = "alignjustify" }
}
},
new
{
title = "Tables",
icon = "table",
items = new[]
{
new { title = "Left", selector = "table", classes = "left", icon = "alignleft" },
new { title = "Right", selector = "table", classes = "right", icon = "alignright" },
new { title = "Full-width", selector = "table", classes = "fullwidth", icon = "alignjustify" }
}
});
I have been trying to make recurring events in fullcalendar, I really find dow feature helpful, but I really want to add date ranges to it.
In other words, dow : [1] will repeat a task for every single Monday, the problems is, I want to make it visible only in a date range I set.
You can not set ranges by using dow, you have to perform some custom functionality.
Lets suppose that you have fetched events data from your database which contains multiple event objects. each event object has start date end date property and also to and from properties which contains date range , isRecurring is a Boolean property which we will add true in case of recurring events otherwise it will be false.
Remember the recurring events take start and end time without date, you only need to give them time slots, like start = "16:00" and end = "20:00" You can extract time by using moment js like i did while initializing my event object
{
title:'Recurring Event',
start: moment.utc(event.start).format('HH:mm'),
end: moment.utc(event.end).format('HH:mm'),
isRecurrring: event.isRecurring,
ranges: [{
start: moment(event.from),
end: moment(event.to),
}],
}
I have used moment.utc() to ignore the timezone.
Now override the eventRender function while initializing your fullCalendar. Your eventRender function will be
eventRender: function(event, element, view){
if (event.isRecurrring) {
return (event.ranges.filter(function(range){
return (moment(event.start).isBefore(range.end) &&
moment(event.end).isAfter(range.start));
}).length) > 0;
}
}
You coulded set ranges as this example:
repeatingEvents.push({
title: "From: " + inputDateStart + " To: " + inputDateFinish,
start: vm.timeStart,
end: vm.timeFinish,
dow: listDay,
ranges: [{
start: dateStart,
end: dateFinish
}]
})
$("#calendar").fullCalendar("refetchEvents");
So you can use both "dow" and "ranges". Hope help for you!
function createCalendar() {
vm.uiConfig = timeProfileFactory.getCalendarConfig();
vm.uiConfig.calendar.eventClick = eventClick;
vm.uiConfig.calendar.eventDrop = alertOnDrop;
vm.uiConfig.calendar.eventResize = alertOnResize;
vm.uiConfig.calendar.eventRender = eventRender;
vm.uiConfig.calendar.select = selectSlot;
vm.uiConfig.calendar.header.center = "title";
vm.events = function(start, end, timezone, callback) {
callback(repeatingEvents);
}
vm.eventSources = [vm.events];
};
function selectSlot(start, end, jsEvent, view) {
var allDay = !start.hasTime() && !end.hasTime();
var offset = ((new Date()).getTimezoneOffset())/60;
var dateStart = (new Date(start)).setHours(0, 0, 0, 0);
dateStart = new Date(dateStart);
dateStart.setHours(dateStart.getHours() - offset);
dateStart = dateStart.toISOString();
var timeStart = (new Date(start)).toISOString();
var timeEnd = (new Date(end)).toISOString();
timeStart = timeStart.split('T')[0];
timeEnd = timeEnd.split('T')[0];
var length = repeatingEvents.length;
if(positionEvent == -1 || repeatingEvents.length == 0) {
positionEvent = 0;
} else {
positionEvent = repeatingEvents[length - 1].position + 1;
}
repeatingEvents.push({
title: "From: " + start.format("DD/MM/YYYY"),
start: start.format("HH:mm"),
end: end.format("HH:mm"),
dow: [new Date(start).getDay()],
ranges: [{
start: dateStart,
end: null
}],
position: positionEvent,
allDay: false
});
length++;
if(repeatingEvents[length - 1].end == "00:00") {
repeatingEvents[length - 1].end = "24:00";
}
if(allDay) {
repeatingEvents[length - 1].allDay = true;
repeatingEvents[length - 1].start = null;
repeatingEvents[length - 1].end = null;
}
$("#calendar").fullCalendar("refetchEvents");
};
function eventClick(event, date, jsEvent, view) {
isOpenDialog = true;
for(var i = 0; i < repeatingEvents.length; i++) {
if(repeatingEvents[i].position == event.position && isOpenDialog) {
selectIndex = i;
vm.timeStart = repeatingEvents[i].start;
vm.timeFinish = repeatingEvents[i].end;
vm.dateStart = repeatingEvents[i].title.split(' ')[1];
if(repeatingEvents[i].ranges[0].end == null) {
vm.dateFinish = "";
vm.radioValue = "never";
} else {
vm.dateFinish = repeatingEvents[i].title.split(' ')[3];
vm.radioValue = "on";
}
angular.forEach(vm.checkDays, function(item) {
item.checked = false;
});
angular.forEach(event.dow, function(index) {
vm.checkDays[index].checked = true;
})
openDialog();
break;
}
}
};
function alertOnResize(event, delta, revertFunc, jsEvent, ui, view) {
for(var i in repeatingEvents) {
if(repeatingEvents[i].position == event.position) {
var timeFinish = event.end.format("HH:mm");
if(timeFinish == "00:00") {
timeFinish = "24:00";
}
repeatingEvents[i].end = timeFinish;
break;
}
}
$("#calendar").fullCalendar("refetchEvents");
};
function alertOnDrop(event, delta, revertFunc, jsEvent, ui, view) {
for(var i in repeatingEvents) {
if(repeatingEvents[i].position == event.position) {
if(repeatingEvents[i].allDay || event.allDay) {
revertFunc();
} else {
var timeStart = event.start.format("HH:mm");
var timeFinish = event.end.format("HH:mm");
var dateStart = repeatingEvents[i].ranges[0].start;
var dateFinish = repeatingEvents[i].ranges[0].end;
var oldTimeStart = repeatingEvents[i].start.split(':')[0]*3600 + repeatingEvents[i].start.split(':')[1]*60;
var newTimeStart = timeStart.split(':')[0]*3600 + timeStart.split(':')[1]*60;
var deltaHour = newTimeStart - oldTimeStart;
var deltaDay = (delta/1000 - deltaHour)/86400;
dateStart = new Date(dateStart);
dateStart.setDate(dateStart.getDate() + deltaDay);
dateStart = dateStart.toISOString();
var title;
if(dateFinish != null) {
dateFinish = new Date(dateFinish);
dateFinish.setDate(dateFinish.getDate() + deltaDay);
dateFinish = dateFinish.toISOString();
title = "From: " + moment(dateStart).format("DD/MM/YYYY") + " To: " + moment(dateFinish).format("DD/MM/YYYY");
} else {
title = "From: " + moment(dateStart).format("DD/MM/YYYY");
}
for(var j in event.dow) {
repeatingEvents[i].dow[j] = parseInt(repeatingEvents[i].dow[j]) + deltaDay;
if(repeatingEvents[i].dow[j] > 6) {
repeatingEvents[i].dow.splice(j, 1);
}
}
repeatingEvents[i].start = timeStart;
repeatingEvents[i].end = timeFinish;
repeatingEvents[i].ranges[0].start = dateStart;
repeatingEvents[i].ranges[0].end = dateFinish;
repeatingEvents[i].title = title;
if(timeFinish == "00:00") {
repeatingEvents[i].end = "24:00";
}
$("#calendar").fullCalendar("refetchEvents");
}
break;
}
}
};
function eventRender(event, element, view) {
var removeEvent = $("<i class='removeEvent icons8-delete pull-right'></i>");
removeEvent.on("click", function() {
isOpenDialog = false;
vm.removeEvent(event);
});
element.find(".fc-content").prepend(removeEvent);
var result;
if(event.ranges[0].end == null) {
result = (event.ranges.filter(function(range) {
var startConvert = (new Date(event.start)).toISOString();
return (event.start.isAfter(range.start) || startConvert == range.start);
}).length) > 0;
} else {
result = (event.ranges.filter(function(range) {
return (event.start.isBefore(range.end) && event.end.isAfter(range.start));
}).length) > 0;
}
return result;
};
I try to find a way to add a link to a Annotation in Swift MapFramework, this link should forward the user to a WebView, as far i see i can't find any way to add a "touchable" link into a Annotations SubTitle
Here is my Code yet
class CustomPointAnnotation: MKPointAnnotation {
var imageName: String!
}
var info1 = CustomPointAnnotation()
info1.coordinate = CLLocationCoordinate2DMake(42, -84)
info1.title = "Info1"
info1.subtitle = "Subtitle"
info1.imageName = "1.png"
var info2 = CustomPointAnnotation()
info2.coordinate = CLLocationCoordinate2DMake(32, -95)
info2.title = "Info2"
info2.subtitle = "Subtitle"
info2.imageName = "2.png"
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.canShowCallout = true
}
else {
anView.annotation = annotation
}
//Set annotation-specific properties **AFTER**
//the view is dequeued or created...
let cpa = annotation as CustomPointAnnotation
anView.image = UIImage(named:cpa.imageName)
return anView
}
Is there maybe a way to use the UIGestureRecognizer for this?
I already tried it like
var longpress = UILongPressGestureRecognizer(target: self, action: "newInformation:")
longpress.minimumPressDuration = 2.0
info1.addGestureRecognizer(longpress)
But ending with "ViewController.CustomPointAnnotation does not have a member named addGestureRecognizer"
Here is a working solution
override func viewDidLoad() {
super.viewDidLoad()
//1
var lat1:CLLocationDegrees = 40.748708
var long1:CLLocationDegrees = -73.985643
var latDelta1:CLLocationDegrees = 0.01
var longDelta1:CLLocationDegrees = 0.01
var span1:MKCoordinateSpan = MKCoordinateSpanMake(latDelta1, longDelta1)
var location1:CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat1, long1)
var region1:MKCoordinateRegion = MKCoordinateRegionMake(location1, span1)
Map.setRegion(region1, animated: true)
var info1 = CustomPointAnnotation()
info1.coordinate = location1
info1.title = "Test Title1!"
info1.subtitle = "Subtitle1"
info1.imageName = "1.png"
Map.addAnnotation(info1)
//2
var lat2:CLLocationDegrees = 41.748708
var long2:CLLocationDegrees = -72.985643
var latDelta2:CLLocationDegrees = 0.01
var longDelta2:CLLocationDegrees = 0.01
var span2:MKCoordinateSpan = MKCoordinateSpanMake(latDelta2, longDelta2)
var location2:CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat2, long2)
var region2:MKCoordinateRegion = MKCoordinateRegionMake(location2, span2)
var info2 = CustomPointAnnotation()
info2.coordinate = location2
info2.title = "Test Title2!"
info2.subtitle = "Subtitle2"
info2.imageName = "2.png"
Map.addAnnotation(info2)
}
func mapView(mapView: MKMapView!, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == annotationView.rightCalloutAccessoryView {
println("Disclosure Pressed! \(self.title)")
}
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.canShowCallout = true
anView.rightCalloutAccessoryView = UIButton.buttonWithType(.InfoDark) as UIButton
}
else {
anView.annotation = annotation
}
//Set annotation-specific properties **AFTER**
//the view is dequeued or created...
let cpa = annotation as CustomPointAnnotation
anView.image = UIImage(named:cpa.imageName)
return anView
}