I am trying to add the drag and drop functionality to my fancy tree. However, there seem to be an issue with where i am initializing the jquery library resulting in error messages indicating that the jquery function i am trying to use is not available etc.
Specific error message = app.js:24 jQuery.Deferred exception: $(...).perfectScrollbar is not a function TypeError: $(...).perfectScrollbar is not a function
If i were to directly initialize a perfect scroll bar, it will continue reflecting other libraries are not a function etc
Simplistic overview of code (Edited to show that master blade is already requiring jquery once)
--Master Blade--
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}" #if (config('voyager.multilingual.rtl')) dir="rtl" #endif>
<head>
<title>#yield('page_title', setting('admin.title') . " - " . setting('admin.description'))</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}"/>
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" rel="stylesheet">
<!-- Favicon -->
<link rel="shortcut icon" href="{{ voyager_asset('images/logo-icon.png') }}" type="image/x-icon">
<!-- App CSS -->
<link rel="stylesheet" href="{{ voyager_asset('css/app.css') }}">
<!-- fancy tree jquery/css-->
#yield('css')
#if(config('voyager.multilingual.rtl'))
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-rtl/3.4.0/css/bootstrap-rtl.css">
<link rel="stylesheet" href="{{ voyager_asset('css/rtl.css') }}">
#endif
<!-- Few Dynamic Styles -->
<style type="text/css">
.voyager .side-menu .navbar-header {
background:#FFFFFF;
border-color:#FFFFFF;
{{--background:{{ config('voyager.primary_color','#22A7F0') }};--}}
{{--border-color:{{ config('voyager.primary_color','#22A7F0') }};--}}
}
.widget .btn-primary{
border-color:{{ config('voyager.primary_color','#22A7F0') }};
}
.widget .btn-primary:focus, .widget .btn-primary:hover, .widget .btn-primary:active, .widget .btn-primary.active, .widget .btn-primary:active:focus{
background:{{ config('voyager.primary_color','#22A7F0') }};
}
.voyager .breadcrumb a{
color:{{ config('voyager.primary_color','#22A7F0') }};
}
.app-container .side-menu .panel.widget h5 {
float: left;
display: block;
position: absolute;
top: 0px;
width: 180px;
text-align: left;
opacity: 0;
transition: opacity .3s ease;
margin-top: 17px;
left: 68px;
overflow: hidden;
height: 29px;
}
.app-container .side-menu .panel.widget h6 {
float: left;
display: block;
position: absolute;
top: 15px;
width: 180px;
text-align: left;
opacity: 0;
transition: opacity .3s ease;
margin-top: 17px;
left: 68px;
overflow: hidden;
height: 29px;
}
.app-container.expanded .panel.widget h5 {
opacity: 1;
}
.app-container.expanded .panel.widget h6 {
opacity: 1;
}
.app-container .side-menu:hover .panel.widget h5 {
opacity: 1;
}
.app-container .side-menu:hover .panel.widget h6 {
opacity: 1;
}
</style>
#if(!empty(config('voyager.additional_css')))<!-- Additional CSS -->
#foreach(config('voyager.additional_css') as $css)<link rel="stylesheet" type="text/css" href="{{ asset($css) }}">#endforeach
#endif
#yield('head')
</head>
<body class="voyager #if(isset($dataType) && isset($dataType->slug)){{ $dataType->slug }}#endif">
<div id="voyager-loader">
<?php $admin_loader_img = Voyager::setting('admin.loader', ''); ?>
#if($admin_loader_img == '')
<img src="{{ voyager_asset('images/logo-icon.png') }}" alt="Voyager Loader">
#else
<img src="{{ Voyager::image($admin_loader_img) }}" alt="Voyager Loader">
#endif
</div>
<?php
if (starts_with(Auth::user()->avatar, 'http://') || starts_with(Auth::user()->avatar, 'https://')) {
$user_avatar = Auth::user()->avatar;
} else {
$user_avatar = Voyager::image(Auth::user()->avatar);
}
?>
<div class="app-container">
<div class="fadetoblack visible-xs"></div>
<div class="row content-container">
#include('voyager::dashboard.navbar')
#include('voyager::dashboard.sidebar')
<script>
(function(){
var appContainer = document.querySelector('.app-container'),
sidebar = appContainer.querySelector('.side-menu'),
navbar = appContainer.querySelector('nav.navbar.navbar-top'),
loader = document.getElementById('voyager-loader'),
hamburgerMenu = document.querySelector('.hamburger'),
sidebarTransition = sidebar.style.transition,
navbarTransition = navbar.style.transition,
containerTransition = appContainer.style.transition;
sidebar.style.WebkitTransition = sidebar.style.MozTransition = sidebar.style.transition =
appContainer.style.WebkitTransition = appContainer.style.MozTransition = appContainer.style.transition =
navbar.style.WebkitTransition = navbar.style.MozTransition = navbar.style.transition = 'none';
if (window.localStorage && window.localStorage['voyager.stickySidebar'] == 'true') {
appContainer.className += ' expanded no-animation';
loader.style.left = (sidebar.clientWidth/2)+'px';
hamburgerMenu.className += ' is-active no-animation';
}
navbar.style.WebkitTransition = navbar.style.MozTransition = navbar.style.transition = navbarTransition;
sidebar.style.WebkitTransition = sidebar.style.MozTransition = sidebar.style.transition = sidebarTransition;
appContainer.style.WebkitTransition = appContainer.style.MozTransition = appContainer.style.transition = containerTransition;
})();
</script>
<!-- Main Content -->
<div class="container-fluid">
<div class="side-body padding-top">
#yield('page_header')
<div id="voyager-notifications"></div>
#yield('content')
</div>
</div>
</div>
</div>
#include('voyager::partials.app-footer')
<!-- Javascript Libs -->
<script type="text/javascript" src="{{ voyager_asset('js/app.js') }}"></script>
<!-- <script type="text/javascript" src="{{ voyager_asset('js/app.js') }}"></script> -->
<script>
#if(Session::has('alerts'))
let alerts = {!! json_encode(Session::get('alerts')) !!};
helpers.displayAlerts(alerts, toastr);
#endif
#if(Session::has('message'))
// TODO: change Controllers to use AlertsMessages trait... then remove this
var alertType = {!! json_encode(Session::get('alert-type', 'info')) !!};
var alertMessage = {!! json_encode(Session::get('message')) !!};
var alerter = toastr[alertType];
if (alerter) {
alerter(alertMessage);
} else {
toastr.error("toastr alert-type " + alertType + " is unknown");
}
#endif
</script>
#yield('javascript')
<!-- Javascript Libs -->
<!-- <script type="text/javascript" src="{{ voyager_asset('js/app.js') }}"></script> -->
#if(!empty(config('voyager.additional_js')))<!-- Additional Javascript -->
#foreach(config('voyager.additional_js') as $js)<script type="text/javascript" src="{{ asset($js) }}"></script>#endforeach
#endif
</body>
</html>
--Fancy Tree Blade --
Extends Master Blade
#section('content')
--fancy tree code--
#stop
#section('javascript)
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="/src/jquery-ui-dependencies/jquery.fancytree.ui-deps.js" type="text/javascript"></script>
<script src="/src/jquery.fancytree.js" type="text/javascript"></script>
<script src="/src/jquery.fancytree.dnd.js" type="text/javascript"></script>
<script src="/src/jquery.fancytree.edit.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
// using default options
$("#tree").fancytree({
extensions: ["dnd"],
checkbox: false,
icon: false,
generateIds: true,
dnd: {
autoExpandMS: 400,
focusOnClick: true,
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
dragStart: function(node, data) {
/** This function MUST be defined to enable dragging for the tree.
* Return false to cancel dragging of node.
*/
return true;
},
dragEnter: function(node, data) {
/** data.otherNode may be null for non-fancytree droppables.
* Return false to disallow dropping on node. In this case
* dragOver and dragLeave are not called.
* Return 'over', 'before, or 'after' to force a hitMode.
* Return ['before', 'after'] to restrict available hitModes.
* Any other return value will calc the hitMode from the cursor position.
*/
// Prevent dropping a parent below another parent (only sort
// nodes under the same parent)
/* if(node.parent !== data.otherNode.parent){
return false;
}
// Don't allow dropping *over* a node (would create a child)
return ["before", "after"];
*/
return true;
},
dragDrop: function(node, data) {
/** This function MUST be defined to enable dropping of items on
* the tree.
*/
data.otherNode.moveTo(node, data.hitMode);
}
},
}
Most of the time getting this error
TypeError: $(…).perfectScrollbar is not a function
Is because of the wrong Order of scripts and sometimes it is because of jQuery enabled version. in the master.blade, page bring the #yield('javascript') right after calling #include('voyager::partials.app-footer') and make sure there isn't any js file in #include('voyager::partials.app-footer') if there it will cause the same error again so take out the js file and import it in your master.blade file.
Try this
I am trying to add the drag and drop functionality to my fancy tree. However, there seem to be an issue with where i am initializing the jquery library resulting in error messages indicating that the jquery function i am trying to use is not available etc.
Specific error message = app.js:24 jQuery.Deferred exception: $(...).perfectScrollbar is not a function TypeError: $(...).perfectScrollbar is not a function
If i were to directly initialize a perfect scroll bar, it will continue reflecting other libraries are not a function etc
Simplistic overview of code (Edited to show that master blade is already requiring jquery once)
--Master Blade--
<!DOCTYPE html>
<html lang="{{ config('app.locale') }}" #if (config('voyager.multilingual.rtl')) dir="rtl" #endif>
<head>
<title>#yield('page_title', setting('admin.title') . " - " . setting('admin.description'))</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}"/>
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,700" rel="stylesheet">
<!-- Favicon -->
<link rel="shortcut icon" href="{{ voyager_asset('images/logo-icon.png') }}" type="image/x-icon">
<!-- App CSS -->
<link rel="stylesheet" href="{{ voyager_asset('css/app.css') }}">
<!-- fancy tree jquery/css-->
#yield('css')
#if(config('voyager.multilingual.rtl'))
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-rtl/3.4.0/css/bootstrap-rtl.css">
<link rel="stylesheet" href="{{ voyager_asset('css/rtl.css') }}">
#endif
<!-- Few Dynamic Styles -->
<style type="text/css">
.voyager .side-menu .navbar-header {
background:#FFFFFF;
border-color:#FFFFFF;
{{--background:{{ config('voyager.primary_color','#22A7F0') }};--}}
{{--border-color:{{ config('voyager.primary_color','#22A7F0') }};--}}
}
.widget .btn-primary{
border-color:{{ config('voyager.primary_color','#22A7F0') }};
}
.widget .btn-primary:focus, .widget .btn-primary:hover, .widget .btn-primary:active, .widget .btn-primary.active, .widget .btn-primary:active:focus{
background:{{ config('voyager.primary_color','#22A7F0') }};
}
.voyager .breadcrumb a{
color:{{ config('voyager.primary_color','#22A7F0') }};
}
.app-container .side-menu .panel.widget h5 {
float: left;
display: block;
position: absolute;
top: 0px;
width: 180px;
text-align: left;
opacity: 0;
transition: opacity .3s ease;
margin-top: 17px;
left: 68px;
overflow: hidden;
height: 29px;
}
.app-container .side-menu .panel.widget h6 {
float: left;
display: block;
position: absolute;
top: 15px;
width: 180px;
text-align: left;
opacity: 0;
transition: opacity .3s ease;
margin-top: 17px;
left: 68px;
overflow: hidden;
height: 29px;
}
.app-container.expanded .panel.widget h5 {
opacity: 1;
}
.app-container.expanded .panel.widget h6 {
opacity: 1;
}
.app-container .side-menu:hover .panel.widget h5 {
opacity: 1;
}
.app-container .side-menu:hover .panel.widget h6 {
opacity: 1;
}
</style>
#if(!empty(config('voyager.additional_css')))<!-- Additional CSS -->
#foreach(config('voyager.additional_css') as $css)<link rel="stylesheet" type="text/css" href="{{ asset($css) }}">#endforeach
#endif
#yield('head')
</head>
<body class="voyager #if(isset($dataType) && isset($dataType->slug)){{ $dataType->slug }}#endif">
<div id="voyager-loader">
<?php $admin_loader_img = Voyager::setting('admin.loader', ''); ?>
#if($admin_loader_img == '')
<img src="{{ voyager_asset('images/logo-icon.png') }}" alt="Voyager Loader">
#else
<img src="{{ Voyager::image($admin_loader_img) }}" alt="Voyager Loader">
#endif
</div>
<?php
if (starts_with(Auth::user()->avatar, 'http://') || starts_with(Auth::user()->avatar, 'https://')) {
$user_avatar = Auth::user()->avatar;
} else {
$user_avatar = Voyager::image(Auth::user()->avatar);
}
?>
<div class="app-container">
<div class="fadetoblack visible-xs"></div>
<div class="row content-container">
#include('voyager::dashboard.navbar')
#include('voyager::dashboard.sidebar')
<script>
(function(){
var appContainer = document.querySelector('.app-container'),
sidebar = appContainer.querySelector('.side-menu'),
navbar = appContainer.querySelector('nav.navbar.navbar-top'),
loader = document.getElementById('voyager-loader'),
hamburgerMenu = document.querySelector('.hamburger'),
sidebarTransition = sidebar.style.transition,
navbarTransition = navbar.style.transition,
containerTransition = appContainer.style.transition;
sidebar.style.WebkitTransition = sidebar.style.MozTransition = sidebar.style.transition =
appContainer.style.WebkitTransition = appContainer.style.MozTransition = appContainer.style.transition =
navbar.style.WebkitTransition = navbar.style.MozTransition = navbar.style.transition = 'none';
if (window.localStorage && window.localStorage['voyager.stickySidebar'] == 'true') {
appContainer.className += ' expanded no-animation';
loader.style.left = (sidebar.clientWidth/2)+'px';
hamburgerMenu.className += ' is-active no-animation';
}
navbar.style.WebkitTransition = navbar.style.MozTransition = navbar.style.transition = navbarTransition;
sidebar.style.WebkitTransition = sidebar.style.MozTransition = sidebar.style.transition = sidebarTransition;
appContainer.style.WebkitTransition = appContainer.style.MozTransition = appContainer.style.transition = containerTransition;
})();
</script>
<!-- Main Content -->
<div class="container-fluid">
<div class="side-body padding-top">
#yield('page_header')
<div id="voyager-notifications"></div>
#yield('content')
</div>
</div>
</div>
</div>
#include('voyager::partials.app-footer')
#yield('javascript')
<!-- Javascript Libs -->
<script type="text/javascript" src="{{ voyager_asset('js/app.js') }}"></script>
<!-- <script type="text/javascript" src="{{ voyager_asset('js/app.js') }}"></script> -->
<script>
#if(Session::has('alerts'))
let alerts = {!! json_encode(Session::get('alerts')) !!};
helpers.displayAlerts(alerts, toastr);
#endif
#if(Session::has('message'))
// TODO: change Controllers to use AlertsMessages trait... then remove this
var alertType = {!! json_encode(Session::get('alert-type', 'info')) !!};
var alertMessage = {!! json_encode(Session::get('message')) !!};
var alerter = toastr[alertType];
if (alerter) {
alerter(alertMessage);
} else {
toastr.error("toastr alert-type " + alertType + " is unknown");
}
#endif
</script>
<!-- Javascript Libs -->
<!-- <script type="text/javascript" src="{{ voyager_asset('js/app.js') }}"></script> -->
#if(!empty(config('voyager.additional_js')))<!-- Additional Javascript -->
#foreach(config('voyager.additional_js') as $js)<script type="text/javascript" src="{{ asset($js) }}"></script>#endforeach
#endif
</body>
</html>
--Fancy Tree Blade --
Extends Master Blade
#section('content')
--fancy tree code--
#stop
#section('javascript)
<script type="text/javascript">
$(function(){
// using default options
$("#tree").fancytree({
extensions: ["dnd"],
checkbox: false,
icon: false,
generateIds: true,
dnd: {
autoExpandMS: 400,
focusOnClick: true,
preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
dragStart: function(node, data) {
/** This function MUST be defined to enable dragging for the tree.
* Return false to cancel dragging of node.
*/
return true;
},
dragEnter: function(node, data) {
/** data.otherNode may be null for non-fancytree droppables.
* Return false to disallow dropping on node. In this case
* dragOver and dragLeave are not called.
* Return 'over', 'before, or 'after' to force a hitMode.
* Return ['before', 'after'] to restrict available hitModes.
* Any other return value will calc the hitMode from the cursor position.
*/
// Prevent dropping a parent below another parent (only sort
// nodes under the same parent)
/* if(node.parent !== data.otherNode.parent){
return false;
}
// Don't allow dropping *over* a node (would create a child)
return ["before", "after"];
*/
return true;
},
dragDrop: function(node, data) {
/** This function MUST be defined to enable dropping of items on
* the tree.
*/
data.otherNode.moveTo(node, data.hitMode);
}
},
}
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="//code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="/src/jquery-ui-dependencies/jquery.fancytree.ui-deps.js" type="text/javascript"></script>
<script src="/src/jquery.fancytree.js" type="text/javascript"></script>
<script src="/src/jquery.fancytree.dnd.js" type="text/javascript"></script>
<script src="/src/jquery.fancytree.edit.js" type="text/javascript"></script>
Related
I am using modal popup with fullcalendar jquery plugin to display my event details on my ASP.NET mvc application and I get my json events from the database. In the event details in the popup, I display the details using jquery.text() methods; I have a url as part of the event data details, how do i make this url clickable to open in another tab in the modal pop up.
<h2>Organiser</h2>
<html>
<head>
<meta charset='utf-8' />
<link href='~/Content/Site.css' rel='stylesheet' />
<link href='~/Content/main.css' rel='stylesheet' />
<link href='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.min.css' rel='stylesheet' />
<link href='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.min.css' rel='stylesheet' />
<link href='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/timegrid/main.min.css' rel='stylesheet' />
<link href='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/list/main.min.css' rel='stylesheet' />
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/core/main.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/interaction/main.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/daygrid/main.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/timegrid/main.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/4.2.0/list/main.min.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
plugins: ['interaction', 'dayGrid', 'timeGrid', 'list'],
contentHeight: 820,
weekends: false,
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,listMonth'
},
defaultView: 'dayGridMonth',
eventLimit: true, // allow "more" link when too many events
eventClick: function (arg) {
$('#modalBody > #title').text(arg.event.title);
$('#modalSchool').text(arg.event.extendedProps.school);
$('#modalYear').text(arg.event.extendedProps.year);
$('#modalStaffs').text(arg.event.extendedProps.staffs);
$('#modalDescription').text(arg.event.extendedProps.description);
$('#modalWhen').text(arg.event.start);
$('#modalEnd').text(arg.event.end);
$('#modalRecord').text(arg.event.extendedProps.recordID);
$('#modalUrl').text(arg.event.extendedProps.url);
$('#calendarModal').modal();
//var $link = $('div#modalUrl');
//$('.modalUrl').click(function () {
// window.open($link)
//});
},
events: function (fetchInfo, successCallback, failureCallback) //function to run whenever the calendar needs events
{
$.ajax({
type: "GET",
url: '#Url.Action("GetData", "Home")',
data: { start: fetchInfo.startStr, end: fetchInfo.endStr },
success: function (data) {
var events = [];
$.each(data, function (i, v) {
events.push({
title: v.School,
start: moment(v.Date).format("YYYY-MM-DD HH:mm"),
end: moment(v.EndTime).format("YYYY-MM-DD HH:mm"),
color: v.Color,
backgroundColor: v.Background,
allDay: v.FullDay,
extendedProps: {
description: v.EventType,
staffs: v.Staffs,
recordID: v.Record,
url: v.URL
}
});
});
successCallback(events); //pass the events back to fullCalendar
},
error: function (error) {
alert('fetching events failed');
console.log(error);
failureCallback(error);
}
});
}
});
calendar.render();
});
</script>
<style>
html,
body {
margin: 0;
padding: 0;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
#calendar {
max-width: 1120px;
margin: 40px auto;
}
.fc-daygrid-event {
white-space: normal !important;
align-items: normal !important;
}
.fc .fc-toolbar-title {
font-size: 1.3em !important;
margin: 0;
}
.fc .fc-button {
font-size: 0.8em;
}
</style>
</head>
<body>
<div class="row">
<div class="col-md-12 col-xs-12">
<div id='calendar' style="margin-top: 20px; "></div>
</div>
</div>
<div id="calendarModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title" style="font-weight: 700;">Event Details</h4>
</div>
<div id="modalBody" class="modal-body">
<div id="modalDescription" style="margin-top:2px;"> <h4> At </h4></div>
<div id="modalSchool" style="margin-top:2px;"></div>
<h4 class="modal-title">On:</h4>
<div id="modalWhen" style="margin-top:2px; white-space:nowrap; overflow: hidden; max-width: 128pt;"></div>
<h4 class="modal-title">To</h4>
<div id="modalEnd" style="margin-top:2px; white-space:nowrap; overflow: hidden; max-width: 128pt;"></div>
<h4 class="modal-title">Staff Members Booked:</h4>
<div id="modalStaffs" style="margin-top:2px;"></div>
<h4 class="modal-title" style=" width: 20%; float: left;">Record ID:</h4>
<div id="modalRecord" style="margin-top:2px;"></div>
<h4 class="modal-title">Url</h4>
<div id="modalUrl" style="margin-top:2px;"></div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
</div>
</div>
</div>
</div>
</body>
</html>
I have to unsuccessfully wrap the in ahref tag, also unsuccessfully tried to use onclick.
You can write the URL into the href property of an <a href element, so it forms a hyperlink.
It could be something simple like:
$('#modalUrl').html("<a href='" + arg.event.extendedProps.url + "'>" + arg.event.extendedProps.url + "</a>");
here I want to add two different class to two button using x-editable angular.
<div ng-app="app" ng-controller="Ctrl">
<div>Email: {{ user.email || 'empty' }}</div>
</div>
you need to configure for all the buttons at once like so
app.run(function(editableOptions, editableThemes) {
editableOptions.theme = 'bs3';
editableThemes.bs3.buttonsClass = 'class1';
});
var app = angular.module("app", ["xeditable"]);
app.run(function(editableOptions, editableThemes) {
editableOptions.theme = 'bs3';
editableThemes.bs3.buttonsClass = 'class1';
});
app.controller('Ctrl', function($scope) {
$scope.user = {
name: 'awesome user'
};
});
div[ng-app] {
margin: 50px;
}
.class1 {
color: green !important;
}
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<link href="http://vitalets.github.io/angular-xeditable/dist/css/xeditable.css" rel="stylesheet" />
<script src="http://vitalets.github.io/angular-xeditable/dist/js/xeditable.js"></script>
<h4>Angular-xeditable Customize input (Bootstrap 3)</h4>
<div ng-app="app" ng-controller="Ctrl">
<a href="#" editable-text="user.name" e-required e-placeholder="Enter name" e-class="class1 class2">
{{ (user.name || 'empty') | uppercase }}
</a>
</div>
here I am using Angular x-editable. I want to add the class directly to the input element and buttons
<div ng-app="app" ng-controller="Ctrl">
<div>Email: {{ user.email || 'empty' }}</div>
</div>
How about using e-class="class1 class2" refer here
var app = angular.module("app", ["xeditable"]);
app.run(function(editableOptions) {
editableOptions.theme = 'bs3';
});
app.controller('Ctrl', function($scope) {
$scope.user = {
name: 'awesome user'
};
});
div[ng-app] {
margin: 50px;
}
.class1 {
color: green !important;
}
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<link href="http://vitalets.github.io/angular-xeditable/dist/css/xeditable.css" rel="stylesheet"/>
<script src="http://vitalets.github.io/angular-xeditable/dist/js/xeditable.js"></script>
<h4>Angular-xeditable Customize input (Bootstrap 3)</h4>
<div ng-app="app" ng-controller="Ctrl">
<a href="#" editable-text="user.name" e-required e-placeholder="Enter name" e-class="class1 class2">
{{ (user.name || 'empty') | uppercase }}
</a>
</div>
I have an HTML file which displays 2 lists using AngularJS file with 2 controllers and a service. The lists are arrays which are being correctly updated in the model, as evidenced by the console.log output. But the HTML doesn't display the updated list2 (data stored in the angularJS service). Can someone tell where I am going wrong?
Tried looking at the API, angular directives, Controller As syntax and inheritance concepts.
index.html
<!DOCTYPE html>
<html lang="en" ng-app="ShoppingListCheckOff">
<head>
<title>Shopping List Check Off</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="styles/bootstrap.min.css" />
<script src="angular.min.js"></script>
<script src="app.js"></script>
<style>
.emptyMessage {
font-weight: bold;
color: red;
font-size: 1.2em;
}
li {
margin-bottom: 7px;
font-size: 1.2em;
}
li > button {
margin-left: 6px;
}
button > span {
color: green;
}
</style>
</head>
<body>
<div class="container">
<h1>Shopping List Check Off</h1>
<div class="row">
<!-- To Buy List -->
<div class="col-md-6" ng-controller="ToBuyController as toBuy">
<h2>To Buy:</h2>
<ul>
<li ng-repeat="item in toBuy.list">
Buy {{ item.name }} {{ item.quantity }}
<button ng-click="toBuy.bought($index)" class="btn btn-default">
<span class="glyphicon glyphicon-ok"></span> Bought
</button>
</li>
</ul>
<div ng-if="!toBuy.list.length" class="emptyMessage">Everything is bought!</div>
</div>
<!-- Already Bought List -->
<div class="col-md-6">
<h2>Already Bought:</h2>
<ul>
<li ng-repeat="item in bought.list">Bought {{ item.quantity }} {{ item.name }}</li>
</ul>
<div ng-if="!bought.list.length" class="emptyMessage">Nothing bought yet.</div>
</div>
</div>
</div>
</body>
</html>
App.js
(function() {
'use strict';
angular
.module('ShoppingListCheckOff', [])
.controller('ToBuyController', ToBuyController)
.controller('AlreadyBoughtController', AlreadyBoughtController)
.service('ShoppingListCheckOffService', ShoppingListCheckOffService);
ToBuyController.$inject = ['ShoppingListCheckOffService'];
function ToBuyController(ShoppingListCheckOffService) {
var toBuy = this;
toBuy.list = ShoppingListCheckOffService.getList(1);
toBuy.bought = function(itemIndex) {
ShoppingListCheckOffService.transfer(itemIndex);
};
}
AlreadyBoughtController.$inject = ['ShoppingListCheckOffService'];
function AlreadyBoughtController(ShoppingListCheckOffService) {
var bought = this;
bought.list = ShoppingListCheckOffService.getList(2);
}
function ShoppingListCheckOffService() {
var service = this;
// List of shopping items
var list1 = [
{ name: 'Cookies', quantity: 10 },
{ name: 'Bananas', quantity: 100 },
{ name: 'Toys', quantity: 6 },
{ name: 'Dildos', quantity: 300 },
{ name: 'Yaakovs', quantity: 1 }
];
var list2 = [];
service.transfer = function(itemIndex) {
list2 = list2.concat(list1.splice(itemIndex, 1));
console.log('List 1', list1);
console.log('List 2', list2);
};
service.getList = function(num) {
if (num == 1) {
return list1;
}
if (num == 2) {
return list2;
}
};
}
})();
The issue is that concat does not change the original array. It creates a new array. When you do list2 = list2.concat(list1.splice(itemIndex, 1)); you are setting list2 to a new array but bought.list is still set to the old array so it doesn't change.
One solution would be to
replace
list2 = list2.concat(list1.splice(itemIndex, 1));
with
list2.push(list1.splice(itemIndex, 1)[0]);
Is it possible to have a single layer visible on the map in this ESRI tutorial LayerList widget ?
Each time you click on a layer, the previous one should deactivate. So you always have only one layer on the map.
Michelle
Updated answer with version 4 of the API.
It is possible to add the functionality at creating the widget using 2 features.
The listItemCreatedFunction function-
https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-LayerList.html#listItemCreatedFunction
According to the api:
Specifies a function that accesses each ListItem. Each list item can be modified according to its modifiable properties. Actions can be added to list items using the actionsSections property of the ListItem.
and the operationalItems property-
https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-LayerList.html#operationalItems
According to the api:
A collection of ListItems representing operational layers.
var LayerListWidget = new LayerList({
listItemCreatedFunction: (event) => {
var itemView = event.item; // layer-view of selection
itemView.watch("visible", (event) => {
LayerListWidget.operationalItems.forEach((layerView) => {
if (layerView.layer.id != itemView.layer.id) {
layerView.visible = false;
}
});
});
},
view: view,
});
I managed to write a code for you . Check it and let me know :
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Layer List Dijit</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.20/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css">
<script language="javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<style>
html, body, .container, #map {
height:100%;
width:100%;
margin:0;
padding:0;
margin:0;
font-family: "Open Sans";
}
#map {
padding:0;
}
#layerListPane{
width:25%;
}
.esriLayer{
background-color: #fff;
}
.esriLayerList .esriList{
border-top:none;
}
.esriLayerList .esriTitle {
background-color: #fff;
border-bottom:none;
}
.esriLayerList .esriList ul{
background-color: #fff;
}
</style>
<script>var dojoConfig = { parseOnLoad: true };var busy=false;</script>
<script src="https://js.arcgis.com/3.20/"></script>
<script>
require([
"esri/arcgis/utils",
"esri/dijit/LayerList",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function(
arcgisUtils,
LayerList
) {
//Create a map based on an ArcGIS Online web map id
arcgisUtils.createMap("f63fed3f87fc488489e27c026fa5d434", "map").then(function(response){
var myWidget = new LayerList({
map: response.map,
layers: arcgisUtils.getLayerList(response)
},"layerList");
myWidget.on("toggle",function(evt){
if(busy) return;
selectedLayerSubIndex = evt.subLayerIndex;
if(selectedLayerSubIndex) return;
selectedLayerIndex = evt.layerIndex;
visibility = evt.visible;
elm = $("#layerListPane input[type=checkbox][data-layer-index="+selectedLayerIndex+"]:not([data-sublayer-index])");
otherCheckedElems = $("#layerListPane input[type=checkbox][data-layer-index!="+selectedLayerIndex+"]:not([data-sublayer-index]):checked");
if(visibility){
busy=true;
otherCheckedElems.each(function () {
$(this).click();
});
busy=false;
}
else{
checkedLength = otherCheckedElems.length
if(checkedLength==0) setTimeout("elm.click();", 100);
}
})
myWidget.startup();
});
});
</script>
</head>
<body class="claro">
<div class="container" data-dojo-type="dijit/layout/BorderContainer"
data-dojo-props="design:'headline',gutters:false">
<div id="layerListPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'right'">
<div id="layerList"></div>
</div>
<div id="map" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'"></div>
</div>
</body>
</html>