AngularJS Compiling Model Like StackOverflow - html

Good day everyone, right now i'm trying to create a textbox like this (stackoverflow textbox) using angularJS .. but im having difficulties on doing so , i have to replace **SOME TEXT HERE** to strong SOME TEXT HERE /strong here's my code ..
$(document).ready(function() {
var app = angular.module("appModule", [], function($interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
});
/* ALLOW ANGULAR TO RENDER HTML OUTPUT */
app.directive('compile', ['$compile', function($compile) {
return function(scope, element, attrs) {
scope.$watch(function(scope) {
return scope.$eval(attrs.compile);
},
function(value) {
element.html(value);
$compile(element.contents())(scope);
}
)
};
}]);
/* CONTROLLER FOR PROFILE TICKER */
app.controller("ProfileTickerController", function($rootScope, $scope, dataService, FileUploader) {
// INITIAL VALUES FOR PROFILE TICKER
$scope.ticker = '';
$scope.previous = '';
$scope.edit = false;
$scope.editTicker = function() {
$scope.previous = $scope.ticker;
if ($scope.ticker == "<span class='color-light-grey'>Ticker not set</span>") {
$scope.ticker = "";
}
$scope.edit = true;
}
$scope.cancelEdit = function() {
$scope.ticker = $scope.previous;
$scope.edit = false;
}
$scope.saveTicker = function() {
if ($scope.ticker == "") {
$scope.ticker = "<span class='color-light-grey'>Ticker not set</span>";
}
$scope.edit = false;
}
$scope.$watch('ticker', function() {
if ($scope.ticker == undefined) {
$scope.ticker = "";
}
})
$scope.init = function(id) {
var postData = 'profileID=' + id;
// SETUP AJAX CONFIG
var config = {
"method": "POST",
"url": "ajax/getTicker.php",
"data": postData,
"headers": {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded'
}
};
// AJAX TO GET PROFILE TICKER
dataService.ajaxThis(config).then(function mySuccess(response) {
// CHECK IF AJAX SUCCESSFUL
if (response.status != 200) {
console.log('Ajax error! Profile ticker not fetched. Please reload the page and try again.');
} else {
// GET PROFILE TICKER
if (response.data == "") {
$scope.ticker = "<span class='color-light-grey'>Ticker not set</span>";
} else {
$scope.ticker = response.data;
}
}
});
}
$scope.$on('profileLoaded', function(e, id) {
$scope.init(id);
});
});
})
.textarea-non-resize {
resize: none;
}
.grey-box {
background: #efefef;
border: 1px solid #dedede;
padding: 10px;
}
#ticker {
height: 42px;
background-color: #fff;
border-top: 1px solid #dedede;
border-bottom: 1px solid #dedede;
font-family: 'Oswald', sans-serif;
text-transform: uppercase;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<script src="script.js"></script>
<body ng-app="appModule" class="ng-scope">
<div class="row">
<div class="col-xs-12 col-sm-12" ng-controller="ProfileTickerController">
<div class="form-group">
<label for="subject">
Ticker
<span ng-show="!edit">
<i class="glyphicon glyphicon-pencil"></i>
</span>
<span ng-show="edit">
<i class="glyphicon glyphicon-ok"></i>
<i class="glyphicon glyphicon-remove"></i>
</span>
</label>
<textarea name="ticker_edit" id="ticker_edit" class="form-control textarea-non-resize" ng-model="ticker" ng-show="edit" placeholder="Customize your ticker here" required cols="50" rows="4" style="margin-bottom: 10px;"></textarea>
<div class="grey-box">
Preview:
<div id="ticker" class="text-center">
<h3 compile="ticker"></h3>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
There's a script error here, but it's working fine in my computer. So anyway how would i replace the said string above using that compiler ?

How about using a Regex to replace the value before you inject it into the element's HTML?
// replace bold text
value = value.replace(/\*\*(.*)\*\*/g, "<strong>$1</strong>");
The above is a simple example and you might need to tweak it a bit to fit your purpose, but the general idea is there.

Related

Jquery Animated Counter Up but work automatically on mobile view

I'm building a counter up for a website. It works perfectly but in mobile view it doesnt wait to get user into it. On computer view, it starts when user sees it. But in mobile view, it starts automatically so it ends before user sees it. Any ideas?
$(document).ready(function($) {
//Check if an element was in a screen
function isScrolledIntoView(elem){
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom));
}
//Count up code
function countUp() {
$('.counter').each(function() {
var $this = $(this), // <- Don't touch this variable. It's pure magic.
countTo = $this.attr('data-count');
ended = $this.attr('ended');
if ( ended != "true" && isScrolledIntoView($this) ) {
$({ countNum: $this.text()}).animate({
countNum: countTo
},
{
duration: 5000, //duration of counting
easing: 'swing',
step: function() {
$this.text(Math.floor(this.countNum));
},
complete: function() {
$this.text(this.countNum);
}
});
$this.attr('ended', 'true');
}
});
}
//Start animation on page-load
if ( isScrolledIntoView(".counter") ) {
countUp();
}
//Start animation on screen
$(document).scroll(function() {
if ( isScrolledIntoView(".counter") ) {
countUp();
}
});
});
.counter-box h1 {
font-size: 25px;
}
.counter-box h1 span {
color: #ff9aa2;
}
.counter-box h4 {
font-size: 20px;
margin-bottom: 60px;
}
.counter-box i.fa {
font-size: 30px;
margin-bottom: 10px;
}
.counter-box p {
font-size: 20px;
}
.counter-desc {
font-size: 16px;
opacity: 0.7;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="row counter-box text-center">
<div class="col-12" style="margin-bottom: 15px;">
<h1>Sayılarla Türkiye'de <span style="color: #cc0000;">Test Sitesi</span></h1>
</div>
<div class="col-4 counterH"><i class="fa fa-code"></i>
<p><span class="counter" data-count="33">0</span>+</p>
<span class="counter-desc">Yıllık Hizmet</span></div>
<div class="col-4 counterH"><i class="fa fa-coffee"></i>
<p><span class="counter" data-count="18000">0</span>+</p>
<span class="couenter-desc">Çeşit Ürün</span></div>
<div class="col-4 counterH"><i class="fa fa-bug"></i>
<p><span class="counter" data-count="800">0</span>+</p>
<span class="counter-desc">Personel</span></div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
$(document).ready(function($) {
//Check if an element was in a screen
function isScrolledIntoView(elem){
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom));
}
//Count up code
function countUp() {
$('.counter').each(function() {
var $this = $(this), // <- Don't touch this variable. It's pure magic.
countTo = $this.attr('data-count');
ended = $this.attr('ended');
if ( ended != "true" && isScrolledIntoView($this) ) {
$({ countNum: $this.text()}).animate({
countNum: countTo
},
{
duration: 5000, //duration of counting
easing: 'swing',
step: function() {
$this.text(Math.floor(this.countNum));
},
complete: function() {
$this.text(this.countNum);
}
});
$this.attr('ended', 'true');
}
});
}
//Start animation on page-load
if ( isScrolledIntoView(".counter") ) {
countUp();
}
//Start animation on screen
$(document).scroll(function() {
if ( isScrolledIntoView(".counter") ) {
countUp();
}
});
});
// ]]></script>
I figure out that it happens because of other components. When i enter the page, other components automatically disappear then show up. So our counter starts from top to bottom because of component rendering.

Bootstrap date-picker highlight dates

I need to update calendar with some date highlighted, it's highlighting on initially if I call the function Highlight() where as it's not highlighting when I click the button and try to highlight. What could be the issue.
function Highlight() {
jQuery_cal('.calendar').datepicker('remove');
var eventDates = {};
eventDates[new Date('06/04/2018')] = new Date('06/04/2018');
eventDates[new Date('06/06/2018')] = new Date('06/06/2018');
eventDates[new Date('06/20/2018')] = new Date('06/20/2018');
eventDates[new Date('06/25/2018')] = new Date('06/25/2018');
setUPRecordingCalendar(eventDates);
}
setUPRecordingCalendar({});
//Highlight();
function setUPRecordingCalendar(eventDates) {
// datepicker
jQuery_cal('#calendar').datepicker({
beforeShowDay: function(date) {
var highlight = eventDates[date];
if (highlight) {
return [true, "event", highlight];
} else {
return [true, '', ''];
}
}
});
}
.event a {
background-color: #42B373 !important;
background-image: none !important;
color: #ffffff !important;
}
.ui-datepicker {
font-size: 12px;
margin: 0 0 0 20px;
}
<html>
<body>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.7.1.min.js"></script>
<link rel='stylesheet prefetch' href='https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/smoothness/jquery-ui.css'>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js'></script>
<script src='https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js'></script>
<script type="text/javascript">
var jQuery_cal = $.noConflict(true);
</script>
<div id="demo">
<div style="width:300px;height:225px;" id="calendar"> </div>
</div>
<button onclick="Highlight()"> Highlight</button>
</body>
</html>
Here is the fiddle link https://jsfiddle.net/20tszxbz/

Printing what is inside a modal

I have a modal where I want to print the full contents of it. I don't want anything else printed aside what is within the modal.
Here I created the button within the modal:
This should not be printed...
<button id="btnPrint">Print (this btn should not be printed!)</button>
<hr />
<div id="printThis">
This should BE printed!
</div>
<div id="printThisToo">
This should BE printed, too!
</div>
I have some text next to the button, but this text should not show when you click the button to preview the print view.
Here I wrote some js to show what content should be printed:
document.getElementById("btnPrint").onclick = function() {
printElement(document.getElementById("printThis"));
printElement(document.getElementById("printThisToo"), true, "<hr />");
window.print();
}
function printElement(elem, append, delimiter) {
var domClone = elem.cloneNode(true);
var $printSection = document.getElementById("printSection");
if (!$printSection) {
var $printSection = document.createElement("div");
$printSection.id = "printSection";
document.body.appendChild($printSection);
}
if (append !== true) {
$printSection.innerHTML = "";
}
else if (append === true) {
if (typeof(delimiter) === "string") {
$printSection.innerHTML += delimiter;
}
else if (typeof(delimiter) === "object") {
$printSection.appendChlid(delimiter);
}
}
$printSection.appendChild(domClone);
}
Finally, I wrote some css:
#media screen {
#printSection {
display: none;
}
}
#media print {
body {
font-family: 'Open Sans', sans-serif;
font-size: 12px;
font-weight: 500;
color: #101010;
background: #f6f5fa;
visibility:hidden;
}
#printSection, #printSection {
visibility:visible;
}
#printSection {
position:absolute;
left:0;
top:0;
}
}
When I click the button in the modal, nothing happens and no errors appear in the console. Not sure what the issue is. Any help would be much appreciated.
UPDATED CODE:
(HTML)
<div>
This should not be printed...
<button ng-click="printPreview()">Print (this btn should not be printed!)</button>
</div>
<hr />
<div id="printThis">
This should BE printed!
</div>
(JS)
var app = angular.module('dmdesktop');
app.controller('PrintViewCtrl', rollUpCtrl);
rollUpCtrl.$inject = ['$scope', '$rootScope', '$http', '$uibModal','headersvc','locFiltersvc']
function rollUpCtrl($scope, $rootScope, $http, $uibModal, headersvc, locFiltersvc) {
$scope.printPreview = function() {
printElement(document.getElementById("printThis"));
}
function printElement(elem) {
alert ("printing!");
var domClone = elem.cloneNode(true);
var $printSection = document.getElementById("printSection");
if (!$printSection) {
var $printSection = document.createElement("div");
$printSection.id = "printSection";
document.body.appendChild($printSection);
}
$printSection.innerHTML = "";
$printSection.appendChild(domClone);
window.print();
}
}
(CSS)
same as before
With the updated code and window.print inside a evalAsync function allows you to print the content inside a modal
$scope.$evalAsync(function () {
window.print();
});

Why does HTML <a> tag sometimes work and other times doesn't in a 2 level nested accordion?

I'm using Bootstrap and I'm trying to make an accordion of items nested inside an accordion. So it would be like top level is an accordion containing many physical quantities panels, and each physical quantity panel's content is an accordion containing a list of SI-conversion-factors panels whose content is a list of units of measurements.
Every a tag on the top level accordion works but in the 2nd level accordion some a tags work and some don't.
Download:
You can see for your self by downloading a zip containing minimum amount of code to replicate the problem:
minimal-code.html
collapse.js
jquery-2.2.4.min.js
css.css
Pictures:
I took some pictures before and after clicking one that don't work and one that do work. Pictures are not from the minimal code to replicate problem version.
I like the accordion style to present the data, what would I have to do to make it work? If not, I can try other styles such as collapse or a simple nested list.
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset='utf-8'>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- <script src="jquery-2.2.4.min.js"></script>
<script src="collapse.js"></script>
<link rel="stylesheet" href="css.css"> -->
</head>
<body>
<div aria-multiselectable="true" id="dimension-accordion" role="tablist" data-reactid=".0.3.0.0.1.0">
<div class="panel panel-info" data-reactid=".0.3.0.0.1.0.$79">
<div role="tab" id="heading-dimension-id-79" class="panel-heading" data-reactid=".0.3.0.0.1.0.$79.0">
<a data-toggle="collapse" data-parent="#dimension-accordion" href="#collapse-dimension-id-79" aria-expanded="false" aria-controls="collapse-dimension-id-79" data-reactid=".0.3.0.0.1.0.$79.0.0">
<h2 data-reactid=".0.3.0.0.1.0.$79.0.0.0"><span class="badge" data-reactid=".0.3.0.0.1.0.$79.0.0.0.0">31</span><span data-reactid=".0.3.0.0.1.0.$79.0.0.0.1">current = {"A" 1}</span></h2>
</a>
</div>
<div id="collapse-dimension-id-79" aria-labelledby="heading-dimension-id-79" role="tabpanel" class="panel-collapse collapse" data-reactid=".0.3.0.0.1.0.$79.1">
<div id="accordion-conversion-factor-for-79" role="tablist" aria-multiselectable="true" data-reactid=".0.3.0.0.1.0.$79.1.0">
<div class="panel panel-default" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835">
<div role="tab" id="0.999835" class="panel-heading" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0">
<a data-toggle="collapse" data-parent="#accordion-conversion-factor-for-79" href="#collapse-id-0.999835" aria-expanded="false" aria-controls="collapse-id-0.999835" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0.0">
<h3 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0.0.0"><span class="badge" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0.0.0.0">4</span><span data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0.0.0.1">0.999835</span></h3>
</a>
</div>
<div id="collapse-id-0.999835" aria-labelledby="0.999835" role="tabpanel" class="panel-collapse collapse" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1">
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1.$4058">intamp</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1.$3015">intampere</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1.$4207">intamperes</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1.$4175">intamps</h4>
</div>
</div>
<div class="panel panel-default" data-reactid=".0.3.0.0.1.0.$79.1.0.$1">
<div role="tab" id="1" class="panel-heading" data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0">
<a data-toggle="collapse" data-parent="#accordion-conversion-factor-for-79" href="#collapse-id-1" aria-expanded="false" aria-controls="collapse-id-1" data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0.0">
<h3 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0.0.0"><span class="badge" data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0.0.0.0">7</span><span data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0.0.0.1">1</span></h3>
</a>
</div>
<div id="collapse-id-1" aria-labelledby="1" role="tabpanel" class="panel-collapse collapse" data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1">
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$3269">A</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$2566">amp</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$1900">ampere</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$1857">amperes</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$303">amps</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$4186">galvat</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$604">galvats</h4>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
CSS:
.panel {
margin-bottom: 20px;
background-color: #fff;
border: 1px solid transparent;
border-radius: 4px;
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
}
.panel-info {
border-color: #bce8f1;
}
.panel-info > .panel-heading {
color: #31708f;
background-color: #d9edf7;
border-color: #bce8f1;
}
.panel-info > .panel-heading + .panel-collapse > .panel-body {
border-top-color: #bce8f1;
}
.panel-info > .panel-heading .badge {
color: #d9edf7;
background-color: #31708f;
}
.panel-info > .panel-footer + .panel-collapse > .panel-body {
border-bottom-color: #bce8f1;
}
.panel-heading {
padding: 10px 15px;
border-bottom: 1px solid transparent;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.badge {
display: inline-block;
min-width: 10px;
padding: 3px 7px;
font-size: 12px;
font-weight: bold;
line-height: 1;
color: #fff;
text-align: center;
white-space: nowrap;
vertical-align: middle;
background-color: #777;
border-radius: 10px;
}
.collapse {
display: none;
}
.collapse.in {
display: block;
}
jquery-2.2.4.min.js:
https://code.jquery.com/jquery-2.2.4.min.js
collapse.js:
/* ========================================================================
* Bootstrap: collapse.js v3.3.6
* http://getbootstrap.com/javascript/#collapse
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
'[data-toggle="collapse"][data-target="#' + element.id + '"]')
this.transitioning = null
if (this.options.parent) {
this.$parent = this.getParent()
} else {
this.addAriaAndCollapsedClass(this.$element, this.$trigger)
}
if (this.options.toggle) this.toggle()
}
Collapse.VERSION = '3.3.6'
Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
toggle: true
}
Collapse.prototype.dimension = function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
if (actives && actives.length) {
activesData = actives.data('bs.collapse')
if (activesData && activesData.transitioning) return
}
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
if (actives && actives.length) {
Plugin.call(actives, 'hide')
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
.attr('aria-expanded', true)
this.$trigger
.removeClass('collapsed')
.attr('aria-expanded', true)
this.transitioning = 1
var complete = function () {
this.$element
.removeClass('collapsing')
.addClass('collapse in')[dimension]('')
this.transitioning = 0
this.$element
.trigger('shown.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
if (this.transitioning || !this.$element.hasClass('in')) return
var startEvent = $.Event('hide.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var dimension = this.dimension()
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
this.$element
.addClass('collapsing')
.removeClass('collapse in')
.attr('aria-expanded', false)
this.$trigger
.addClass('collapsed')
.attr('aria-expanded', false)
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
.removeClass('collapsing')
.addClass('collapse')
.trigger('hidden.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
Collapse.prototype.getParent = function () {
return $(this.options.parent)
.find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
.each($.proxy(function (i, element) {
var $element = $(element)
this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
}, this))
.end()
}
Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
var isOpen = $element.hasClass('in')
$element.attr('aria-expanded', isOpen)
$trigger
.toggleClass('collapsed', !isOpen)
.attr('aria-expanded', isOpen)
}
function getTargetFromTrigger($trigger) {
var href
var target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
return $(target)
}
// COLLAPSE PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.collapse
$.fn.collapse = Plugin
$.fn.collapse.Constructor = Collapse
// COLLAPSE NO CONFLICT
// ====================
$.fn.collapse.noConflict = function () {
$.fn.collapse = old
return this
}
// COLLAPSE DATA-API
// =================
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
var $this = $(this)
if (!$this.attr('data-target')) e.preventDefault()
var $target = getTargetFromTrigger($this)
var data = $target.data('bs.collapse')
var option = data ? 'toggle' : $this.data()
Plugin.call($target, option)
})
}(jQuery);

AngularJS / NgMap - Zoom to selected pins and center

I have an SPA that is displaying pins on a map that are filtered down by Region, State/Province and ultimately City. I have Lat/Lng in my locations, and I'm passing that to the map markup and filtering it on each select list selection. I'm running in to issues with getting the map to focus on each region as it's subsequently filtered down.
Is there a way to recenter when using the markup to display the markers, or to do that would I need to rework the code to handle displaying the markers in the JS instead of the markup?
See Plunkr: http://plnkr.co/edit/qaLFYD?p=preview
var app = angular.module('plunker', ['ngRoute', 'angular.filter', 'ngMap']);
app.controller('MainCtrl', function($scope, $anchorScroll, $location, $http) {
// GET data
$scope.dataObject = data.List;
$scope.locationObject = data.Locations;
$scope.cart = [];
$scope.addToCart = function(index) {
$scope.cart.push(index);
$scope.cartCount = $scope.cart.length;
}
$scope.activeRow = function(index) {
$scope.selectedRow = index;
$location.hash();
$anchorScroll('anchor-' + index);
}
$scope.gotoAnchor = function(x) {
var newHash = 'anchor' + x;
}
$scope.$on('mapInitialized', function(event, map) {
map.setOptions({
draggable: true
});
});
}).filter('byFilter', function() {
return function(items, location) {
var filtered = [];
if (!location || !items.length) {
return items;
}
items.forEach(function(itemElement, itemIndex) {
itemElement.Locations.forEach(function(locationElement, locationIndex) {
if (filterCountry(locationElement, location) || filterRegion(locationElement, location) || filterCity(locationElement, location))
filtered.push(itemElement);
});
});
return filtered;
};
function filterCountry(locationElement, location) {
var exist = false;
if (!location.Region) {
exist = true;
return exist;
} else exist = (locationElement.Region === location.Region);
return exist;
}
function filterRegion(locationElement, location) {
var exist = false;
if (!location.StateName) {
exist = true;
return exist;
}
locationElement.Sites.forEach(function(siteElement, siteIndex) {
if (siteElement.State === location.StateName) {
exist = true;
return false;
}
});
return exist;
}
function filterCity(locationElement, location) {
var exist = false;
if (!location.CityName) {
exist = true;
return exist;
}
locationElement.Sites.forEach(function(siteElement, siteIndex) {
if (siteElement.City === location.CityName) {
exist = true;
return false;
}
});
return exist;
}
}).filter('ForMap', function() {
return function(items, location) {
var filtered = [];
if (!items) {
return items;
}
var state = (location.state ? location.state.StateName : '');
var city = (location.city ? location.city.CityName : '');
var region = (location.region ? location.region.Region : '');
items.forEach(function(itemElement, itemIndex) {
itemElement.Locations.forEach(function(locationElement, locationIndex) {
if (locationElement.Region === region || !region) {
locationElement.Sites.forEach(function(siteElement, siteIndex) {
if ((siteElement.State == state && !city) || siteElement.City == city || (!state && !city)) {
filtered.push(siteElement);
return false;
}
});
}
});
});
return filtered;
};
});
/* Put your css in here */
body {
background: #eee;
}
div.cart {
display: block;
height: 70px;
background: silver;
margin-left: 20px;
width: 200px;
padding: 5px 10px;
margin-bottom: 20px;
margin-top: 20px;
}
.cart h1 {
color: #fff;
line-height: 20px;
}
.item-list-wrapper {
height: 400px;
width: 90%;
border: 1px solid #ddd;
overflow-y: scroll;
margin-left: 20px;
}
.item-list-wrapper table td {
padding: 10px;
vertical-align: middle;
margin-bottom: 10px;
font-size: 12px;
}
.item-list {
height: auto;
width: 100%;
margin-bottom: 10px;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
border: 1px solid #fff;
background: #efefe4;
}
.col-num {
width: 100px;
}
.col-compound {
width: 80px;
}
.filters {
width: 100%;
clear: both;
margin-left: 20px;
}
.filters select {
width: 200px;
}
.filters column {
height: 100px;
width: 200px;
display: inline-block;
margin: 0;
padding: 0;
}
.filters select {
display: inline-block;
}
.region {
font-weight: bolder;
}
.state {
font-weight: normal;
}
.map-wrapper {
width: 490px;
height: 490px;
}
map {
width: 490px;
height: 490px;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link data-require="bootstrap#*" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<link data-require="bootstrap-css#*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="angular-ui.min.css" />
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script data-require="angular.js#1.4.x" data-semver="1.4.7" src="https://code.angularjs.org/1.4.7/angular-messages.js"></script>
<script data-require="ui-bootstrap#*" data-semver="0.13.3" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.1/ui-bootstrap.min.js"></script>
<script src="angular-filter.min.js"></script>
<script src="angular-route.min.js"></script>
<script src="ng-map.min.js"></script>
<script src="angular-ui.min.js"></script>
<script src="angular-scroll.min.js"></script>
<script src="app.js"></script>
<script src="http://zbl.me/test/103015.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-view=""></div>
<div class="filters">
<h2>Filter results</h2>
<column>
<select name="selectRegion" class="form-control" ng-model="selectRegion" ng-options="location as location.Region for location in locationObject | orderBy: location.Region:reverse">
<option value="">Select Region</option>
</select>
<select name="selectState" class="form-control" ng-disabled="!selectRegion" ng-model="selectState" ng-options="state as state.StateName for state in selectRegion.States">
<option value="">Select State/Province/Country</option>
</select>
<select name="selectCity" class="form-control" ng-disabled="!selectState" ng-model="selectCity" ng-options="city as city.CityName for city in selectState.Cities">
<option value="">Select City</option>
</select>
</column>
<column>
<select name="selectPhase" class="form-control" ng-model="selectPhase" ng-options="data.Phase as data.Phase for data in dataObject | unique: 'Phase' | orderBy: 'Phase' ">
<option value="">Select Phase</option>
</select>
<select name="selectNumber" class="form-control" ng-model="selectNumber" ng-options="data.Number as data.Number for data in dataObject | unique: 'Compound' | orderBy: 'Compound' ">
<option value="">Select Number</option>
</select>
</column>
</div>
<div map-lazy-load="http://maps.google.com/maps/api/js">
<map zoom="1" scrollwheel="false">
<span ng-repeat="site in (dataObject | ForMap : {region:selectRegion, state:selectState, city:selectCity}) track by $index" id="{{data.Id}}">
<marker position="[{{site.Latitude}},{{site.Longitude}}]"></marker>
</span>
</map>
</div>
<div class="cart">
<h1>Cart: {{cartCount}}</h1>
</div>
<div class="item-list-wrapper">
<table class="table table-condensed table-hover">
<tr ng-repeat="data in dataObject | byFilter | filterBy:['Phase']: selectPhase | filterBy:['Number']: selectNumber track by $index" ng-click="activeRow($index)">
<td class="column">{{data.Phase}}</td>
<td class="column col-num">{{data.Number}}</td>
<td class="column col-compound">{{data.Compound}}</td>
<td>
<span ng-repeat="location in data.Locations track by $index" class="region">{{ location.Region}}:
<span ng-repeat="site in location.Sites | unique: 'State'" class="state">{{site.State}}
</span>
</span>
</td>
<td>Add
</td>
</tr>
</table>
</div>
</body>
</html>
Looks like adding zoom-to-include-markers="true" to the map element achieves this.
<div map-lazy-load="http://maps.google.com/maps/api/js">
<map zoom="1" scrollwheel="false" zoom-to-include-markers="auto">
<span ng-repeat="site in (dataObject | ForMap : {region:selectRegion, state:selectState, city:selectCity}) track by $index" id="{{data.Id}}">
<marker position="[{{site.Latitude}},{{site.Longitude}}]"></marker>
</span>
</map>
</div>