Основной файл сценария, доступный через угловое приложение
Я новичок в Angular и столкнулся с проблемой, из-за которой мои основные файлы скриптов по какой-то причине не видны моим частичным файлам. Я вижу, что основной файл работает корректно за пределами моих частичных представлений и представлений.
Вот моя установка:
index.html (приложение)
<!doctype html>
<html ng-app="testapplication">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>Test!</title>
<link rel="stylesheet/less" type="text/css" href="assets/stylesheets/theme/rocket_theme.less" />
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<!-- Core Theme Less -->
<script type="text/javascript">
less = {
env: "development",
logLevel: 0,
async: true
};
</script>
</head>
<body class="">
<!-- Start: Main -->
<div id="main">
<div ng-include src="'app/views/shared/top_header.html'"></div>
<div ng-view></div>
</div>
<!-- End: Main -->
<!-- JQuery -->
<script src="vendor/jquery/dist/jquery.min.js"></script>
<script src="vendor/jquery/dist/jquery-ui.min.js"></script>
<!-- Theme Core JS -->
<script src="assets/javascripts/theme/custom.js"></script>
<script src="assets/javascripts/theme/utility/utility.js"></script>
<script src="assets/javascripts/theme/main.js"></script>
<!-- Application - Plugins -->
<script src="vendor/underscore/underscore-min.js"></script>
<script src="vendor/less/dist/less.min.js"></script>
<script src="vendor/holderjs/holder.js"></script>
<script src="vendor/hello/dist/hello.all.min.js"></script>
<script src="vendor/chartjs/Chart.min.js"></script>
<!-- Angular - Resources -->
<script src="vendor/angular/angular.min.js"></script>
<script src="vendor/angular-resource/angular-resource.min.js"></script>
<script src="vendor/restangular/dist/restangular.min.js"></script>
<script src="vendor/angular-route/angular-route.min.js"></script>
<script src="vendor/angular-chart.js/dist/angular-chart.js"></script>
<script src="vendor/ng-currency/dist/ng-currency.min.js"></script>
<script src="vendor/angular-animate/angular-animate.js"></script>
<script src="vendor/angular-utils-pagination/dirPagination.js"></script>
<!-- Angular - Application -->
<script src="assets/javascripts/angular/app.js"></script>
<script src="assets/javascripts/angular/routes/routes.js"></script>
<script src="assets/javascripts/angular/services/shared-properties.js"> </script>
<!-- Application - Controllers -->
<script src="assets/javascripts/angular/controllers/topHeader_ctrl.js"></script>
<script type="text/javascript">
jQuery(document).ready(function() {
// Init Theme Core
Core.init();
console.log('init');
});
</script>
</body>
</html>
Если я инициализирую файл основного скрипта в контроллере, то он работает только для этого конкретного контроллера:
Контроллер верхнего заголовка
app.controller('HeaderCtrl', function($scope,$http,sharedProperties,Restangular) {
Core.init();//works but only for this controller
$scope.gotoUrl = function(url){
window.location.href = "#/" + url;
}
});
Мне нужно иметь возможность инициализировать ядро один раз, чтобы оно было доступно для каждой части моего приложения.
main.js
'use strict';
/*! main.js - v0.1.1
* http://admindesigns.com/
* Copyright (c) 2015 Admin Designs;*/
/* Core theme functions required for
* most of the themes vital functionality */
var Core = function(options) {
// Variables
var Body = $('body');
// SideMenu Functions
var runSideMenu = function(options) {
// If sidebar is fixed init custom scrollbar plugin
// if ($('#sidebar_left.affix').length && !$('body').hasClass('sb-l-m')) {
// $('.sidebar-left-content').scroller();
// }
// Sidebar state naming conventions:
// "sb-l-o" - SideBar Left Open
// "sb-l-c" - SideBar Left Closed
// "sb-l-m" - SideBar Left Minified
// Same naming convention applies to right sidebar
// SideBar Left Toggle Function
var sidebarLeftToggle = function() {
// We check to see if the the user has closed the entire
// leftside menu. If true we reopen it, this will result
// in the menu resetting itself back to a minified state.
// A second click will fully expand the menu.
if (Body.hasClass('sb-l-c') && options.collapse === "sb-l-m") {
Body.removeClass('sb-l-c');
}
// Toggle sidebar state(open/close)
Body.toggleClass(options.collapse).removeClass('sb-r-o').addClass('sb-r-c');
triggerResize();
};
// SideBar Right Toggle Function
var sidebarRightToggle = function() {
// toggle sidebar state(open/close)
if (options.siblingRope === true && !Body.hasClass('mobile-view') && Body.hasClass('sb-r-o')) {
Body.toggleClass('sb-r-o sb-r-c').toggleClass(options.collapse);
}
else {
Body.toggleClass('sb-r-o sb-r-c').addClass(options.collapse);
}
triggerResize();
};
// Sidebar Left Collapse Entire Menu event
$('.sidebar-toggle-mini').on('click', function(e) {
e.preventDefault();
// Close Menu
Body.addClass('sb-l-c');
triggerResize();
// After animation has occured we toggle the menu.
// Upon the menu reopening the classes will be toggled
// again, effectively restoring the menus state prior
// to being hidden
if (!Body.hasClass('mobile-view')) {
setTimeout(function() {
Body.toggleClass('sb-l-m sb-l-o');
}, 250);
}
});
// Check window size on load
// Adds or removes "mobile-view" class based on window size
var sbOnLoadCheck = function() {
// Check Body for classes indicating the state of Left and Right Sidebar.
// If not found add default sidebar settings(sidebar left open, sidebar right closed).
if (!$('body.sb-l-o').length && !$('body.sb-l-m').length && !$('body.sb-l-c').length) {
$('body').addClass(options.sbl);
}
if (!$('body.sb-r-o').length && !$('body.sb-r-c').length) {
$('body').addClass(options.sbr);
}
// If window is < 1080px wide collapse both sidebars and add ".mobile-view" class
if ($(window).width() < 1080) {
Body.removeClass('sb-r-o').addClass('mobile-view sb-l-m sb-r-c');
}
};
// Check window size on resize
// Adds or removes "mobile-view" class based on window size
var sbOnResize = function() {
// If window is < 1080px wide collapse both sidebars and add ".mobile-view" class
if ($(window).width() < 1080 && !Body.hasClass('mobile-view')) {
Body.removeClass('sb-r-o').addClass('mobile-view sb-l-m sb-r-c');
} else if ($(window).width() > 1080) {
Body.removeClass('mobile-view');
} else {
return;
}
};
// Most CSS menu animations are set to 300ms. After this time
// we trigger a single global window resize to help catch any 3rd
// party plugins which need the event to resize their given elements
var triggerResize = function() {
// If sidebar is fixed init custom scrollbar plugin
if ($('#sidebar_left.affix').length && $('body').hasClass('sb-l-m')) {
$('.sidebar-left-content').scroller('destroy');
}
setTimeout(function() {
$(window).trigger('resize');
}, 300)
};
// Functions Calls
sbOnLoadCheck();
$("#toggle_sidemenu_l").click(sidebarLeftToggle);
$("#toggle_sidemenu_r").click(sidebarRightToggle);
// Attach debounced resize handler
var rescale = function() {
sbOnResize();
}
var lazyLayout = _.debounce(rescale, 300);
$(window).resize(lazyLayout);
// 2. LEFT USER MENU TOGGLE
// Find user menu item length
var usermenuItems = $('.user-menu').find('a');
// Toggle open the user menu
$('.sidebar-menu-toggle').click(function(e) {
e.preventDefault();
// Toggle Class to signal state change
$('.user-menu').toggleClass('usermenu-open').slideToggle('fast');
// If menu is closed apply animation
if ($('.user-menu').hasClass('usermenu-open')) {
usermenuItems.addClass('animated fadeIn');
}
});
// 3. LEFT MENU LINKS TOGGLE
$('.sidebar-menu li a.accordion-toggle').click(function(e) {
// Any menu item with the accordion class is a dropdown submenu. Thus we prevent default actions
e.preventDefault();
// Any menu item with the accordion class is a dropdown submenu. Thus we prevent default actions
if ($('body').hasClass('sb-l-m') && !$(this).parents('ul.sub-nav').length) {
return;
}
// Any menu item with the accordion class is a dropdown submenu. Thus we prevent default actions
if (!$(this).parents('ul.sub-nav').length) {
$('a.accordion-toggle.menu-open').next('ul').slideUp('fast', 'swing', function() {
$(this).attr('style', '').prev().removeClass('menu-open');
});
}
// Any menu item with the accordion class is a dropdown submenu. Thus we prevent default actions
else {
var activeMenu = $(this).next('ul.sub-nav');
var siblingMenu = $(this).parent().siblings('li').children('a.accordion-toggle.menu-open').next('ul.sub-nav')
activeMenu.slideUp('fast', 'swing', function() {
$(this).attr('style', '').prev().removeClass('menu-open');
});
siblingMenu.slideUp('fast', 'swing', function() {
$(this).attr('style', '').prev().removeClass('menu-open');
});
}
// Now we expand targeted menu item, add the ".open-menu" class
// and remove any left over inline jQuery animation styles
if (!$(this).hasClass('menu-open')) {
$(this).next('ul').slideToggle('fast', 'swing', function() {
$(this).attr('style', '').prev().toggleClass('menu-open');
});
}
});
}
// jQuery Helper Functions
var runHelpers = function() {
// Disable selection
$.fn.disableSelection = function() {
return this
.attr('unselectable', 'on')
.css('user-select', 'none')
.on('selectstart', false);
};
// Test for IE, Add body class if version 9
function msieversion() {
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {
var ieVersion = parseInt(ua.substring(msie + 5, ua.indexOf(".", msie)));
if (ieVersion === 9) {$('body').addClass('no-js ie' + ieVersion);}
return ieVersion;
}
else { return false; }
}
msieversion();
// Clean up helper that removes any leftover
// animation classes on the primary content container
// If left it can cause z-index and visibility problems
setTimeout(function() {
$('#content').removeClass('animated fadeIn');
},800);
}
// Delayed Animations
var runAnimations = function() {
// Add a class after load to prevent css animations
// from bluring pages that have load intensive resources
setTimeout(function() {
$('body').addClass('onload-check');
}, 100);
// Delayed Animations
// data attribute accepts delay(in ms) and animation style
// if only delay is provided fadeIn will be set as default
// eg. data-animate='["500","fadeIn"]'
$('.animated-delay[data-animate]').each(function() {
var This = $(this)
var delayTime = This.data('animate');
var delayAnimation = 'fadeIn';
// if the data attribute has more than 1 value
// it's an array, reset defaults
if (delayTime.length > 1 && delayTime.length < 3) {
delayTime = This.data('animate')[0];
delayAnimation = This.data('animate')[1];
}
var delayAnimate = setTimeout(function() {
This.removeClass('animated-delay').addClass('animated ' + delayAnimation)
.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
This.removeClass('animated ' + delayAnimation);
});
}, delayTime);
});
// "In-View" Animations
// data attribute accepts animation style and offset(in %)
// eg. data-animate='["fadeIn","40%"]'
$('.animated-waypoint').each(function(i, e) {
var This = $(this);
var Animation = This.data('animate');
var offsetVal = '35%';
// if the data attribute has more than 1 value
// it's an array, reset defaults
if (Animation.length > 1 && Animation.length < 3) {
Animation = This.data('animate')[0];
offsetVal = This.data('animate')[1];
}
var waypoint = new Waypoint({
element: This,
handler: function(direction) {
console.log(offsetVal)
if (This.hasClass('animated-waypoint')) {
This.removeClass('animated-waypoint').addClass('animated ' + Animation)
.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
This.removeClass('animated ' + Animation);
});
}
},
offset: offsetVal
});
});
}
// Header Functions
var runHeader = function() {
// Searchbar - Mobile modifcations
$('.navbar-search').on('click', function(e) {
var This = $(this);
var searchForm = This.find('input');
var searchRemove = This.find('.search-remove');
// Don't do anything unless in mobile mode
if (!$('body.mobile-view').length) { return; }
// Open search bar and add closing icon if one isn't found
This.addClass('search-open');
if (!searchRemove.length) {
This.append('<div class="search-remove"></div>');
}
// Fadein remove btn and focus search input on animation complete
setTimeout(function() {
This.find('.search-remove').fadeIn();
searchForm.focus();
searchForm.one('keydown', function() {
$(this).val('');
});
},330)
// If remove icon clicked close search bar
if ($(e.target).attr('class') == 'search-remove') {
This.removeClass('search-open');
This.find('.search-remove').remove();
}
});
// custom animation for header content dropdown
if ($('.dropdown-item-slide').length) {
$('.dropdown-item-slide').on('shown.bs.dropdown', function() {
var This = $(this);
setTimeout(function() {
This.addClass('slide-open');
}, 20);
});
$('.dropdown-item-slide').on('hidden.bs.dropdown', function() {
$(this).removeClass('slide-open');
});
}
// Init jQuery Multi-Select for navbar user dropdown
if ($("#user-status").length) {
$('#user-status').multiselect({
buttonClass: 'btn btn-default btn-sm',
buttonWidth: 100,
dropRight: false
});
}
if ($("#user-role").length) {
$('#user-role').multiselect({
buttonClass: 'btn btn-default btn-sm',
buttonWidth: 100,
dropRight: true
});
}
// Persistent tooltips. Use this class to prevent a menu
// dropdown from closing when clicking content inside of it
if ($('.dropdown-menu.dropdown-persist').length) {
$('.dropdown-menu.dropdown-persist').on('click', function(e) {
e.stopPropagation();
var Target = $(e.target);
// stopping event propagation will also disable multiselects from working
// in areas such as the user menu dropdown. This helps correct that
function closeMulti() {
Target.parents('.dropdown-persist').find('.btn-group').each(function() {
if ($(this).children('.multiselect').length) {
$(this).removeClass('open');
}
});
};
if (Target.hasClass('multiselect') || Target.parent().hasClass('multiselect')) {
closeMulti();
Target.parents('.btn-group').toggleClass('open');
} else {
closeMulti()
}
});
}
// Sliding Topbar Metro Menu
var menu = $('#topbar-dropmenu');
var items = menu.find('.metro-tile');
var metroBG = $('.metro-modal');
// Toggle menu and active class on icon click
$('.topbar-menu-toggle').on('click', function() {
menu.slideToggle(230).toggleClass('topbar-menu-open');
$(items).addClass('animated animated-short fadeInDown').css('opacity', 1);
// Create Modal for hover effect
if (!metroBG.length) {
metroBG = $('<div class="metro-modal"></div>').appendTo('body');
}
setTimeout(function() {
metroBG.fadeIn();
}, 380);
});
// If modal is clicked close menu
$('body').on('click', '.metro-modal', function() {
metroBG.fadeOut('fast');
setTimeout(function() {
menu.slideToggle(150).toggleClass('topbar-menu-open');
}, 250);
});
}
// Tray related Functions
var runTrays = function() {
// Match height of tray with the height of body
var trayMatch = $('.tray[data-tray-height="match"]');
if (trayMatch.length) {
// Loop each tray and set height to match body
trayMatch.each(function() {
var Height = $('body').height();
$(this).height(Height);
});
};
// Debounced resize handler
var rescale = function() {
if ($(window).width() < 1000) {
Body.addClass('tray-rescale');
}
else {Body.removeClass('tray-rescale tray-rescale-left tray-rescale-right');}
}
var lazyLayout = _.debounce(rescale, 300);
if (!Body.hasClass('disable-tray-rescale')) {
// Rescale on window resize
$(window).resize(lazyLayout);
// Rescale on load
rescale();
}
}
// Form related Functions
var runFormElements = function() {
// Init Jquery Sortable, if present
if ($(".sortable").length) {
$(".sortable").sortable();
$(".sortable").disableSelection();
}
var Tooltips = $("[data-toggle=tooltip]");
// Init Bootstrap tooltips, if present
if (Tooltips.length) {
if (Tooltips.parents('#sidebar_left')) {
Tooltips.tooltip({
container: $('body'),
template: '<div class="tooltip tooltip-white" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
});
} else {
Tooltips.tooltip();
}
}
// Init Bootstrap Popovers, if present
if ($("[data-toggle=popover]").length) {
$('[data-toggle=popover]').popover();
}
// Init Bootstrap persistent tooltips. This prevents a
// popup from closing if a checkbox it contains is clicked
$('.dropdown-menu .dropdown-persist').click(function(event) {
event.stopPropagation();
});
// Prevents a dropdown menu from closing when a navigation
// menu it contains is clicked (panel/tab menus)
$('.dropdown-menu .nav-tabs li a').click(function(event) {
event.preventDefault();
event.stopPropagation();
$(this).tab('show')
});
// if btn has ".btn-states" class we monitor it for user clicks. On Click we remove
// the active class from its siblings and give it to the button clicked.
// This gives the button set a menu like feel or state
if ($('.btn-states').length) {
$('.btn-states').click(function() {
$(this).addClass('active').siblings().removeClass('active');
});
}
}
return {
init: function(options) {
// Set Default Options
var defaults = {
sbl: "sb-l-o", // sidebar left open onload
sbr: "sb-r-c", // sidebar right closed onload
collapse: "sb-l-m", // sidebar left collapse style
siblingRope: true
// Setting this true will reopen the left sidebar
// when the right sidebar is closed
};
// Extend Default Options.
var options = $.extend({}, defaults, options);
// Call Core Functions
runHelpers();
runAnimations();
runSideMenu(options);
runTrays();
runFormElements();
runHeader();
}
}
}();
// Global Library of Theme colors for Javascript plug and play use
var bgPrimary = '#4a89dc',
bgPrimaryL = '#5d9cec',
bgPrimaryLr = '#83aee7',
bgPrimaryD = '#2e76d6',
bgPrimaryDr = '#2567bd',
bgSuccess = '#70ca63',
bgSuccessL = '#87d37c',
bgSuccessLr = '#9edc95',
bgSuccessD = '#58c249',
bgSuccessDr = '#49ae3b',
bgInfo = '#3bafda',
bgInfoL = '#4fc1e9',
bgInfoLr = '#74c6e5',
bgInfoD = '#27a0cc',
bgInfoDr = '#2189b0',
bgWarning = '#f6bb42',
bgWarningL = '#ffce54',
bgWarningLr = '#f9d283',
bgWarningD = '#f4af22',
bgWarningDr = '#d9950a',
bgDanger = '#e9573f',
bgDangerL = '#fc6e51',
bgDangerLr = '#f08c7c',
bgDangerD = '#e63c21',
bgDangerDr = '#cd3117',
bgAlert = '#967adc',
bgAlertL = '#ac92ec',
bgAlertLr = '#c0b0ea',
bgAlertD = '#815fd5',
bgAlertDr = '#6c44ce',
bgSystem = '#37bc9b',
bgSystemL = '#48cfad',
bgSystemLr = '#65d2b7',
bgSystemD = '#2fa285',
bgSystemDr = '#288770',
bgLight = '#f3f6f7',
bgLightL = '#fdfefe',
bgLightLr = '#ffffff',
bgLightD = '#e9eef0',
bgLightDr = '#dfe6e9',
bgDark = '#3b3f4f',
bgDarkL = '#424759',
bgDarkLr = '#51566c',
bgDarkD = '#2c2f3c',
bgDarkDr = '#1e2028',
bgBlack = '#283946',
bgBlackL = '#2e4251',
bgBlackLr = '#354a5b',
bgBlackD = '#1c2730',
bgBlackDr = '#0f161b';
1 ответ
Если вы выполняете много переписывания DOM и манипулирования атрибутами в базовых библиотеках, то это не сработает ни в одном из случаев, когда рендерится новый вид. Даже если положить его за пределы контроллера, он будет работать для первого загруженного контроллера.
Вы можете сделать что-то вроде
function SomeController($scope) {
$scope.$on('$viewContentLoaded', function(){Core.init();});
}
Вы должны будете сделать это в каждом контроллере.
Лучшая практика - написать директиву.
РЕДАКТИРОВАТЬ: ТАК вот правило большого пальца. Если основные файлы не касаются угловых представлений, лучше оставить их снаружи, в противном случае вам придется делать это, как указано выше.
EDIT2: мое предложение, основанное на добавленном main.js. У него есть правила, которые применяются к общим элементам, таким как выпадающий список. Так что я бы посоветовал вам пойти по угловому пути