Angular example from the web not working - javascript

I'm beginning with Angular and I saw this example in this page http://tutorialzine.com/2013/08/learn-angularjs-5-examples/ and I'm trying to reproduce some of them.
The example 4 looks like something I can use right away in the system I'm working on right now.
I couldn't get it to work integrated on my system, so I isolated the example in a single file and I'm getting the exact same result as in my system.
The console gives the the following error:
angular.js:13236Error: [ng:areq] http://errors.angularjs.org/1.5.0/ng/areq?p0=InstantSearchController&p1=not%20a%20function%2C%20got%20undefined
at Error (native)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:6:416
at sb (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:23:63)
at Sa (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:23:150)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:86:318
at A (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:64:17)
at u (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:65:8)
at g (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:58:136)
at https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:57:279
at https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:21:88
I'm trying to figure out why it says InstantSearchController is not a function, it should be working since it's a copy and paste from a working example from the web.
I was thinking things should be declared in a certain order but even moving things around in the page didn't give me any result.
Maybe the working example and the code being shown are different.
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<style type="text/css">
*{
margin:0;
padding:0;
}
body{
font:15px/1.3 'Open Sans', sans-serif;
color: #5e5b64;
text-align:center;
}
a, a:visited {
outline:none;
color:#389dc1;
}
a:hover{
text-decoration:none;
}
section, footer, header, aside, nav{
display: block;
}
/*-------------------------
The search input
--------------------------*/
.bar{
background-color:#5c9bb7;
background-image:-webkit-linear-gradient(top, #5c9bb7, #5392ad);
background-image:-moz-linear-gradient(top, #5c9bb7, #5392ad);
background-image:linear-gradient(top, #5c9bb7, #5392ad);
box-shadow: 0 1px 1px #ccc;
border-radius: 2px;
width: 400px;
padding: 14px;
margin: 45px auto 20px;
position:relative;
}
.bar input{
background:#fff no-repeat 13px 13px;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkU5NEY0RTlFMTA4NzExRTM5RTEzQkFBQzMyRjkyQzVBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkU5NEY0RTlGMTA4NzExRTM5RTEzQkFBQzMyRjkyQzVBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RTk0RjRFOUMxMDg3MTFFMzlFMTNCQUFDMzJGOTJDNUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RTk0RjRFOUQxMDg3MTFFMzlFMTNCQUFDMzJGOTJDNUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4DjA/RAAABK0lEQVR42pTSQUdEURjG8dOY0TqmPkGmRcqYD9CmzZAWJRHVRIa0iFYtM6uofYaiEW2SRJtEi9YxIklp07ZkWswu0v/wnByve7vm5ee8M+85zz1jbt9Os+WiGkYdYxjCOx5wgFeXUHmtBSzpcCGa+5BJTCjEP+0nKWAT8xqe4ArPGEEVC1hHEbs2oBwdXkM7mj/JLZrad437sCGHOfUtcziutuYu2v8XUFF/4f6vMK/YgAH1HxkBYV60AR31gxkBYd6xAeF3VzMCwvzOBpypX8V4yuFRzX2d2gD/l5yjH4fYQEnzkj4fae5rJulF2sMXVrAsaTWttRFu4Osb+1jEDT71/ZveyhouTch2fINQL9hKefKjuYFfuznXWzXMTabyrvfyIV3M4vhXgAEAUMs7K0J9UJAAAAAASUVORK5CYII=);
border: none;
width: 100%;
line-height: 19px;
padding: 11px 0;
border-radius: 2px;
box-shadow: 0 2px 8px #c4c4c4 inset;
text-align: left;
font-size: 14px;
font-family: inherit;
color: #738289;
font-weight: bold;
outline: none;
text-indent: 40px;
}
ul{
list-style: none;
width: 428px;
margin: 0 auto;
text-align: left;
}
ul li{
border-bottom: 1px solid #ddd;
padding: 10px;
overflow: hidden;
}
ul li img{
width:60px;
height:60px;
float:left;
border:none;
}
ul li p{
margin-left: 75px;
font-weight: bold;
padding-top: 12px;
color:#6e7a7f;
}
</style>
</head>
<body>
<!-- Initialize a new AngularJS app and associate it with a module named "instantSearch"-->
<div ng-app="instantSearch" ng-controller="InstantSearchController">
<div class="bar">
<!-- Create a binding between the searchString model and the text field -->
<input type="text" ng-model="searchString" placeholder="Enter your search terms" />
</div>
<ul>
<!-- Render a li element for every entry in the items array. Notice
the custom search filter "searchFor". It takes the value of the
searchString model as an argument.
-->
<li ng-repeat="i in items | searchFor:searchString">
<img ng-src="{{i.image}}" />
<p>{{i.title}}</p>
</li>
</ul>
</div>
</body>
<script type="text/javascript">
// Define a new module for our app. The array holds the names of dependencies if any.
var app = angular.module("instantSearch", []);
// Create the instant search filter
app.filter('searchFor', function () {
// All filters must return a function. The first parameter
// is the data that is to be filtered, and the second is an
// argument that may be passed with a colon (searchFor:searchString)
return function (arr, searchString) {
if (!searchString) {
return arr;
}
var result = [];
searchString = searchString.toLowerCase();
// Using the forEach helper method to loop through the array
angular.forEach(arr, function (item) {
if (item.title.toLowerCase().indexOf(searchString) !== -1) {
result.push(item);
}
});
return result;
};
});
// The controller
function InstantSearchController($scope) {
// The data model. These items would normally be requested via AJAX,
// but are hardcoded here for simplicity. See the next example for
// tips on using AJAX.
$scope.items = [
{
url: 'http://tutorialzine.com/2013/07/50-must-have-plugins-for-extending-twitter-bootstrap/',
title: '50 Must-have plugins for extending Twitter Bootstrap',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/07/featured_4-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/08/simple-registration-system-php-mysql/',
title: 'Making a Super Simple Registration System With PHP and MySQL',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/08/simple_registration_system-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/08/slideout-footer-css/',
title: 'Create a slide-out footer with this neat z-index trick',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/08/slide-out-footer-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/06/digital-clock/',
title: 'How to Make a Digital Clock with jQuery and CSS3',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/06/digital_clock-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/05/diagonal-fade-gallery/',
title: 'Smooth Diagonal Fade Gallery with CSS3 Transitions',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/05/featured-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/05/mini-ajax-file-upload-form/',
title: 'Mini AJAX File Upload Form',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/05/ajax-file-upload-form-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/04/services-chooser-backbone-js/',
title: 'Your First Backbone.js App – Service Chooser',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/04/service_chooser_form-100x100.jpg'
}
];
}
</script>
</html>

This is because your InstantSearchController is not registered in angular application. You should do it like this
app.controller("InstantSearchController", function (....) {
....
});
Also it is not good idea to bootstrap your application on same element as controller (Either via ng-app attribute or programatically). Application should be "global" and inside of the app there should be controllers

InstantSearchController isn't being defined as a controller. Instead of just creating a function named that, it should be done like this:
app.controller('InstantSearchController', function($scope) { ... });
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<style type="text/css">
*{
margin:0;
padding:0;
}
body{
font:15px/1.3 'Open Sans', sans-serif;
color: #5e5b64;
text-align:center;
}
a, a:visited {
outline:none;
color:#389dc1;
}
a:hover{
text-decoration:none;
}
section, footer, header, aside, nav{
display: block;
}
/*-------------------------
The search input
--------------------------*/
.bar{
background-color:#5c9bb7;
background-image:-webkit-linear-gradient(top, #5c9bb7, #5392ad);
background-image:-moz-linear-gradient(top, #5c9bb7, #5392ad);
background-image:linear-gradient(top, #5c9bb7, #5392ad);
box-shadow: 0 1px 1px #ccc;
border-radius: 2px;
width: 400px;
padding: 14px;
margin: 45px auto 20px;
position:relative;
}
.bar input{
background:#fff no-repeat 13px 13px;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkU5NEY0RTlFMTA4NzExRTM5RTEzQkFBQzMyRjkyQzVBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkU5NEY0RTlGMTA4NzExRTM5RTEzQkFBQzMyRjkyQzVBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RTk0RjRFOUMxMDg3MTFFMzlFMTNCQUFDMzJGOTJDNUEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RTk0RjRFOUQxMDg3MTFFMzlFMTNCQUFDMzJGOTJDNUEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4DjA/RAAABK0lEQVR42pTSQUdEURjG8dOY0TqmPkGmRcqYD9CmzZAWJRHVRIa0iFYtM6uofYaiEW2SRJtEi9YxIklp07ZkWswu0v/wnByve7vm5ee8M+85zz1jbt9Os+WiGkYdYxjCOx5wgFeXUHmtBSzpcCGa+5BJTCjEP+0nKWAT8xqe4ArPGEEVC1hHEbs2oBwdXkM7mj/JLZrad437sCGHOfUtcziutuYu2v8XUFF/4f6vMK/YgAH1HxkBYV60AR31gxkBYd6xAeF3VzMCwvzOBpypX8V4yuFRzX2d2gD/l5yjH4fYQEnzkj4fae5rJulF2sMXVrAsaTWttRFu4Osb+1jEDT71/ZveyhouTch2fINQL9hKefKjuYFfuznXWzXMTabyrvfyIV3M4vhXgAEAUMs7K0J9UJAAAAAASUVORK5CYII=);
border: none;
width: 100%;
line-height: 19px;
padding: 11px 0;
border-radius: 2px;
box-shadow: 0 2px 8px #c4c4c4 inset;
text-align: left;
font-size: 14px;
font-family: inherit;
color: #738289;
font-weight: bold;
outline: none;
text-indent: 40px;
}
ul{
list-style: none;
width: 428px;
margin: 0 auto;
text-align: left;
}
ul li{
border-bottom: 1px solid #ddd;
padding: 10px;
overflow: hidden;
}
ul li img{
width:60px;
height:60px;
float:left;
border:none;
}
ul li p{
margin-left: 75px;
font-weight: bold;
padding-top: 12px;
color:#6e7a7f;
}
</style>
</head>
<body>
<!-- Initialize a new AngularJS app and associate it with a module named "instantSearch"-->
<div ng-app="instantSearch" ng-controller="InstantSearchController">
<div class="bar">
<!-- Create a binding between the searchString model and the text field -->
<input type="text" ng-model="searchString" placeholder="Enter your search terms" />
</div>
<ul>
<!-- Render a li element for every entry in the items array. Notice
the custom search filter "searchFor". It takes the value of the
searchString model as an argument.
-->
<li ng-repeat="i in items | searchFor:searchString">
<img ng-src="{{i.image}}" />
<p>{{i.title}}</p>
</li>
</ul>
</div>
</body>
<script type="text/javascript">
// Define a new module for our app. The array holds the names of dependencies if any.
var app = angular.module("instantSearch", []);
// Create the instant search filter
app.filter('searchFor', function () {
// All filters must return a function. The first parameter
// is the data that is to be filtered, and the second is an
// argument that may be passed with a colon (searchFor:searchString)
return function (arr, searchString) {
if (!searchString) {
return arr;
}
var result = [];
searchString = searchString.toLowerCase();
// Using the forEach helper method to loop through the array
angular.forEach(arr, function (item) {
if (item.title.toLowerCase().indexOf(searchString) !== -1) {
result.push(item);
}
});
return result;
};
});
// The controller
app.controller('InstantSearchController', function($scope) {
// The data model. These items would normally be requested via AJAX,
// but are hardcoded here for simplicity. See the next example for
// tips on using AJAX.
$scope.items = [
{
url: 'http://tutorialzine.com/2013/07/50-must-have-plugins-for-extending-twitter-bootstrap/',
title: '50 Must-have plugins for extending Twitter Bootstrap',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/07/featured_4-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/08/simple-registration-system-php-mysql/',
title: 'Making a Super Simple Registration System With PHP and MySQL',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/08/simple_registration_system-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/08/slideout-footer-css/',
title: 'Create a slide-out footer with this neat z-index trick',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/08/slide-out-footer-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/06/digital-clock/',
title: 'How to Make a Digital Clock with jQuery and CSS3',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/06/digital_clock-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/05/diagonal-fade-gallery/',
title: 'Smooth Diagonal Fade Gallery with CSS3 Transitions',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/05/featured-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/05/mini-ajax-file-upload-form/',
title: 'Mini AJAX File Upload Form',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/05/ajax-file-upload-form-100x100.jpg'
},
{
url: 'http://tutorialzine.com/2013/04/services-chooser-backbone-js/',
title: 'Your First Backbone.js App – Service Chooser',
image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/04/service_chooser_form-100x100.jpg'
}
];
});
</script>
</html>

Related

ListJS: TypeError: list.templater is undefined + Source Map URL: list.js.map (with Wordpress)

I am writing a plugin for wordpress. The idea is to get data from one API, then serve a filtered / remixed version of that data to a listjs container / list through a shortcode. List.js is not working as expected. I'm developing locally and trying to keep this concise, but I have put the entire plugin code base up on github here.
I can render text through the shortcode, so serving HTML appears to be working fine.
When I am trying to use listjs, just to get this example working, however, it's not. I am getting the following errors, warnings, and logs in the JS devtools area of Firefox:
Uncaught TypeError: list.templater is undefined (list.js:497:11)
values http://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.js:497
init http://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.js:481
List http://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.js:520
add http://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.js:307
<anonymous> http://localhost/wordpress/wp-content/plugins/bdh-mbc-mediator-directory/public/js/bdh-mbc-mediator-directory-list-js.js:25
JQMIGRATE: Migrate is installed, version 3.3.2 (jquery-migrate.min.js:2:709) //not an error, but here for completeness
Source map error: Error: request failed with status 404
Resource URL: http://cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.js
Source Map URL: list.js.map 2
Here is what does render on my site: you can see that list.js just isn't really doing what I would like it to, because there's no data being rendered, and there's no pagination (not that I'm sure that would show up with no data). The HTML after the page loads is just a search bar with a button that says "name" next to it:
<div class="wp-container-7 entry-content wp-block-post-content">
<div id="mbcusers">
<input class="fuzzy-search" placeholder="Search">
<button class="sort" data-sort="mbcname">
Sort by name
</button>
<ul class="mbclist"></ul>
<ul class="pagination"></ul>
</div>
</div>
I'm going to do the best to give you the contents of what I think are the relevant files, in order,
// JS 1
var mbcoptions = {
valueNames: [ 'name', 'born' ],
pagination: true,
// Since there are no elements in the list, this will be used as template.
item: '<li><h3 class="name"></h3><p class="born"></p></li>'
};
var mbcvalues = [
{
mbcname: 'Jonny Strömberg',
mbcborn: 1986
},
{
mbcname: 'Jonas Arnklint',
mbcborn: 1985
},
{
mbcname: 'Martina Elm',
mbcborn: 1986
}
];
var mbcUserList = new List('mbcusers', mbcoptions, mbcvalues);
mbcUserList.add({
mbcname: 'Gustaf Lindqvist',
mbcborn: 1983
});
// JS 2
window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/14.0.0\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/14.0.0\/svg\/","svgExt":".svg","source":{"concatemoji":"http:\/\/localhost\/wordpress\/wp-includes\/js\/wp-emoji-release.min.js?ver=6.0.1"}};
/*! This file is auto-generated */
!function(e,a,t){var n,r,o,i=a.createElement("canvas"),p=i.getContext&&i.getContext("2d");function s(e,t){var a=String.fromCharCode,e=(p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,e),0,0),i.toDataURL());return p.clearRect(0,0,i.width,i.height),p.fillText(a.apply(this,t),0,0),e===i.toDataURL()}function c(e){var t=a.createElement("script");t.src=e,t.defer=t.type="text/javascript",a.getElementsByTagName("head")[0].appendChild(t)}for(o=Array("flag","emoji"),t.supports={everything:!0,everythingExceptFlag:!0},r=0;r<o.length;r++)t.supports[o[r]]=function(e){if(!p||!p.fillText)return!1;switch(p.textBaseline="top",p.font="600 32px Arial",e){case"flag":return s([127987,65039,8205,9895,65039],[127987,65039,8203,9895,65039])?!1:!s([55356,56826,55356,56819],[55356,56826,8203,55356,56819])&&!s([55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447],[55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447]);case"emoji":return!s([129777,127995,8205,129778,127999],[129777,127995,8203,129778,127999])}return!1}(o[r]),t.supports.everything=t.supports.everything&&t.supports[o[r]],"flag"!==o[r]&&(t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&t.supports[o[r]]);t.supports.everythingExceptFlag=t.supports.everythingExceptFlag&&!t.supports.flag,t.DOMReady=!1,t.readyCallback=function(){t.DOMReady=!0},t.supports.everything||(n=function(){t.readyCallback()},a.addEventListener?(a.addEventListener("DOMContentLoaded",n,!1),e.addEventListener("load",n,!1)):(e.attachEvent("onload",n),a.attachEvent("onreadystatechange",function(){"complete"===a.readyState&&t.readyCallback()})),(e=t.source||{}).concatemoji?c(e.concatemoji):e.wpemoji&&e.twemoji&&(c(e.twemoji),c(e.wpemoji)))}(window,document,window._wpemojiSettings);
.mbclist {
font-family:sans-serif;
margin:0;
padding:20px 0 0;
}
.mbclist > li {
display:block;
background-color: #eee;
padding:10px;
box-shadow: inset 0 1px 0 #fff;
}
.avatar {
max-width: 150px;
}
img {
max-width: 100%;
}
h3 {
font-size: 16px;
margin:0 0 0.3rem;
font-weight: normal;
font-weight:bold;
}
p {
margin:0;
}
input {
border:solid 1px #ccc;
border-radius: 5px;
padding:7px 14px;
margin-bottom:10px
}
input:focus {
outline:none;
border-color:#aaa;
}
.sort {
padding:8px 30px;
border-radius: 6px;
border:none;
display:inline-block;
color:#fff;
text-decoration: none;
background-color: #28a8e0;
height:30px;
}
.sort:hover {
text-decoration: none;
background-color:#1b8aba;
}
.sort:focus {
outline:none;
}
.sort:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid transparent;
content:"";
position: relative;
top:-10px;
right:-5px;
}
.sort.asc:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #fff;
content:"";
position: relative;
top:13px;
right:-5px;
}
.sort.desc:after {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 5px solid #fff;
content:"";
position: relative;
top:-10px;
right:-5px;
}
.pagination li {
display:inline-block;
padding:5px;
}
<!-- In order, the following JS is loadedin HEAD on the relevant page:
JS2 (shown below in the JS section)
<script src="http://localhost/wordpress/wp-includes/js/wp-emoji-release.min.js?ver=6.0.1" type="text/javascript" defer=""></script>
<script src="http://localhost/wordpress/wp-includes/blocks/navigation/view.min.js?ver=009e29110e016c14bac4ba0ecc809fcd" id="wp-block-navigation-view-js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/list.js/2.3.1/list.js" id="listjs-js"></script>
<script src="http://localhost/wordpress/wp-content/plugins/bdh-mbc-mediator-directory/public/js/bdh-mbc-mediator-directory-list-js.js" id="bdh_mbc_js-js"></script>
<script src="http://localhost/wordpress/wp-includes/js/jquery/jquery.min.js?ver=3.6.0" id="jquery-core-js"></script>
<script src="http://localhost/wordpress/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.3.2" id="jquery-migrate-js"></script>
-->
<div id="mbcusers">
<input class="fuzzy-search" placeholder="Search" />
<button class="sort" data-sort="mbcname">
Sort by name
</button>
<ul class="mbclist"></ul>
<ul class="pagination"></ul>
</div>
I'm not too familiar with namespaces in JS, and I'm concerned the issue is being caused by a naming conflict. Alternatively, perhaps its an "order of load" issue?

Chrome extension State management

I am currently making a chrome extension (This is my first chrome extension) that you can take small notes with and want to keep the user input. I am keeping the user input inside of input classes. How would I be able to store the chrome extension state so that when I reopen it, it will stay the same? Here is the code that I have written so far.
//selectors
const addbutton = document.querySelector(".add");
const addlist = document.querySelector(".note-list");
const noteList = document.querySelector(".note-list")
//event listners
addbutton.addEventListener('click', addNote);
//functions
function addNote(event){
//prevent page refresh
event.preventDefault();
//note div
const noteDiv = document.createElement('div');
noteDiv.classList.add('note');
//create li
const newNote = document.createElement('li');
newNote.classList.add('noteitem');
noteDiv.appendChild(newNote);
//create input
const newInput = document.createElement('input');
newInput.classList.add('noteInput')
newNote.appendChild(newInput);
//append to list
noteList.appendChild(noteDiv);
}
#import url('https://fonts.googleapis.com/css2?family=Montserrat:wght#500&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
}
body{
height: 500px;
width: 400px;
}
h1{
font-family: "Montserrat", sans-serif;
font-size: 20px;
font-weight: lighter;
padding-top: 10px;
padding-bottom: 10px;
}
main{
text-align: center;
}
.title{
box-shadow: 0 2px 2px -2px rgba(0, 0, 0, 0.685);
}
.mainpage{
padding-top: 20px;
}
.add{
font-family: "Montserrat", sans-serif;
font-size: 25px;
font-weight: 400px;
background-color: #00FF33;
width:40px ;
height: 40px;
border-radius: 10px;
border: none;
transition: ease 0.5s;
}
.add:hover{
background-color: #00c026;
}
.note-container{
display: flex;
justify-content: center;
align-items: center;
}
.note-list{
min-width: 30%;
list-style: none;
}
.note{
margin: 0.5rem;
background: whitesmoke;
font-size: 1.5rem;
display: flex;
justify-content: space-between;
border-radius: 7px;
}
.noteitem{
padding: 0.5rem 2rem;
}
.noteInput{
display: block;
margin-right: auto;
margin-left: auto;
border: none;
background-color: whitesmoke;
font-size: 20px;
max-height: 200px;
}
.note li{
flex: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mini Note</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<div class="title">
<h1>Mini note app</h1>
</div>
<section class="mainpage">
<button class="add">+</button>
<div class="note-container">
<ul class="note-list"></ul>
</div>
</section>
</main>
<script src="/popup.js"></script>
</body>
</html>
Thank you
// uses local storage
chrome.storage.local.set({key: value}, function() {
console.log('Value is set to ' + value);
});
// uses synced storage, hits Chrome backend when being set
chrome.storage.sync.set({key: value}, function() {
console.log('Value is set to ' + value);
});
// to retrieve the data, use 'sync' instead of 'local' if using sync
chrome.storage.local.get(['key'], function(result) {
console.log('Value currently is ' + result.key);
});
You'll still need to figure out how you want to organize the note data. For example, you could store all of the notes in an array on the notes key that looks like the following:
{
notes: [
{ id: 1, body: 'First note' },
{ id: 2, body: 'Second note' }
]
}
you have two options :-
you can use localStorage just like in web page for more check here
you can use chrome.storage for more check here

How to extract css values from website page

Is there any way to extract css values from website page using css class name. I want to get all css values and child class values using parent class css name.
For an Example:
Wepage Css :
.container {
width: 80%;
}
.btn-wrap {
padding: 3px;
width: 25%;
text-align: center;
}
.text-box {
margin: 0 auto;
width: 50%;
}
.frm-btn-grp {
padding: 3px;
width: 100%;
text-align: center;
.btn-success {
border: 1px solid green;
padding: 7px 24px;
border-radius: 2px;
color: white;
background-color: green;
width: 100px;
}
}
If i will give .frm-btn-grp as input It will return
.frm-btn-grp {
padding: 3px;
width: 100%;
text-align: center;
.btn-success {
border: 1px solid green;
padding: 7px 24px;
border-radius: 2px;
color: white;
background-color: green;
width: 100px;
}
}
Is this possible?
Here's some webscraping action:
import re
import urllib.request as ureq
sample_url = "https://stackoverflow.com/questions/59685137/how-to-extract-css-values-from-website-page"
with ureq.urlopen(sample_url) as req:
data = req.read().decode('utf-8')
#- Split HTML by line ending; Look for 'text/css' matches
css_lines = [i.strip() for i in data.split('\n') if len(i) > 0 and 'text/css' in i]
#-- Create a simple regular expression to extract the css html
#-- Note: ?P<named_tag> allows for naming each section, but I think
#-- it only works on compiled regular expresions, which isn't a huge
#-- deal.
css_pat = r'href="(?P<css_url>.+)"'
p = re.compile(css_pat)
#-- Create a list and append it with our matches.
css_urls = []
for i in css_lines:
tmp = p.search(i).group('css_url')
if tmp:
css_urls.append(tmp)
Output:
In[4]: css_urls
Out[4]:
['https://cdn.sstatic.net/Shared/stacks.css?v=d0797a2dd6f2',
'https://cdn.sstatic.net/Sites/stackoverflow/primary.css?v=f7becef1b212']
Then, you can do whatever. Iterate the urls to get all of the css data, open and join all the css files into one, etc.
with ureq.urlopen(css_urls[0]) as req:
css_data = req.read().decode('utf-8')
#-- Here's a sample printout of a css file for this page
#-- I added some .replace() statments to make it prettier :-)
print(css_data[:500]
.replace(',', ',\n')
.replace('{', ' {\n\t')
.replace(';', ';\n\t')
.replace('}','\n\t}\n\n')
)
Truncated output:
html,
body,
div,
span,
{...}
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin:0;
padding:0;
border:0;
font:inherit;
font-size:100%;
vertical-align:baseline
}
article,
a

MapBox API exclusive layer switcher

I have thoroughly searched MapBox support and Stack Overflow for an answer on how to create an exclusive layer switcher using the latest MapBox API (1.6.1 as of now). Exclusive in this case means that only 1 layer can be visible/active at a time. I do not want to use the Leaflet Layers Control for design reasons.
With a little help, I have come up with this example, which almost works:
http://bl.ocks.org/sarahkhank/0e5d81998d2d0876856c
For some reason, adding and removing the gridControl breaks the loop. If you use this structure to just add/remove the tileLayer with no gridLayer or gridControl, it works fine. But when you add the grid elements, the last element in the array doesn't show up and messes up the rest of the loop. (In this case 'far'.)
Does anyone have any idea why this is happening? This type of layer switcher is often asked about on MapBox support, so I'm sure many people would be happy to see this come to life. Thanks for your help!!
Posting full code here at the bottom in case my bl.ocks link ever breaks.
<html>
<head>
<title>DC Zoning Map</title>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src='http://api.tiles.mapbox.com/mapbox.js/v1.6.1/mapbox.js'></script>
<link href='http://api.tiles.mapbox.com/mapbox.js/v1.6.1/mapbox.css' rel='stylesheet' />
</head>
<body>
<style>
#zoning-map-container {
position:relative;
float: right;
display: inline;
}
#map_zoning {
position: relative;
float: left;
clear: both;
width:45%;
min-width: 500px;
height: 500px;
right:20px;
margin-top: 10px;
margin-right: 10px;
border: 1px solid #bbb;
}
#map-ui-zoning {
position:relative;
float: left;
list-style:none;
margin:0;padding:0;
left: -20px;
}
#map-ui-zoning a {
font-family: 'Carrois Gothic', sans-serif;
font-size: 12px;
font-weight: 400;
background:#FFF;
color:#5698D0;
float: left;
margin:0;
border:1px solid #BBB;
border-width: 1px 1px 1px 0;
max-width:100px;
padding:8px;
text-decoration:none;
}
#map-ui-zoning li {
display: inline;
}
#map-ui-zoning a:hover { background:#ECF5FA; }
#map-ui-zoning li:last-child a {
border-bottom-width:1px;
-webkit-border-radius:0 3px 3px 0;
border-radius:0 3px 3px 0;
}
#map-ui-zoning li:first-child a {
border-left-width: 1px;
-webkit-border-radius:3px 0 0 3px;
border-radius:3px 0 0 3px;
}
#map-ui-zoning a.active {
background:#5698D0;
border-color:#5698D0;
border-top-color:#BBB;
color:#FFF;
}
.map-tooltip .zone {
font-size: 10px;
line-height: 13px;
font-weight: bold;
}
.map-tooltip .desc {
font-size: 10px;
line-height: 13px;
padding-bottom: 3px;
}
.map-tooltip .focus {
font-size: 13px;
line-height: 16px;
font-weight: bold;
}
.map-tooltip .info {
font-size: 11px;
line-height: 16px;
}
</style>
<div id='zoning-map-container'>
<ul id='map-ui-zoning'>
<li>Maximum Stories</li>
<li>Maximum Height</li>
<li>Maximum FAR</li>
</ul>
<div id='map_zoning'></div>
</div>
<script type='text/javascript'>
var map = L.mapbox.map('map_zoning');
var stamenLayer = L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png', {
attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under CC BY SA.'
}).addTo(map);
map.setView([38.908, -77.029], 11);
var ui = document.getElementById('map-ui-zoning');
var stories = L.mapbox.tileLayer('sarah.28n6ogvi');
var storiesGrid = L.mapbox.gridLayer('sarah.28n6ogvi');
var storiesGridControl = L.mapbox.gridControl(storiesGrid, {follow: false});
var height = L.mapbox.tileLayer('sarah.ofjsv2t9');
var heightGrid = L.mapbox.gridLayer('sarah.ofjsv2t9');
var heightGridControl = L.mapbox.gridControl(heightGrid, {follow: false});
var far = L.mapbox.tileLayer('sarah.2w9x80k9');
var farGrid = L.mapbox.gridLayer('sarah.2w9x80k9');
var farGridControl = L.mapbox.gridControl(farGrid, {follow: false});
var layers = [{
'name': 'stories',
'layer': stories,
'gridLayer': storiesGrid,
'gridControl': storiesGridControl
},
{
'name': 'height',
'layer': height,
'gridLayer': heightGrid,
'gridControl': heightGridControl
},
{
'name': 'far',
'layer': far,
'gridLayer': farGrid,
'gridControl': farGridControl
}
];
$(document).ready(function(layer){
map.addLayer(stories);
map.addLayer(storiesGrid);
map.addControl(storiesGridControl);
});
$('#map-ui-zoning li a').on('click', function() {
$('#map-ui-zoning li a').removeClass('active');
var $el = $(this);
layers.forEach(function(layer) {
if ($el.data('name') !== layer['name']){
map.removeLayer(layer['layer']);
map.removeLayer(layer['gridLayer']);
map.removeControl(layer['gridControl']);
}
else {
map.addLayer(layer['layer']);
map.addLayer(layer['gridLayer']);
map.addControl(layer['gridControl']);
$el.addClass('active');
}
});
});
</script>
I think that when you call map.removeControl(layer['gridControl']) or more generally map.removeLayer you dont test if the layer is already added to the map because otherwise it mapboxjs will try to delete an element that does not exist and this is where your code gets broken .
if ($el.data('name') !== layer['name'])
needs to become
if ($el.data('name') !== layer['name'] && map.hasLayer(layer))
of course you need to change your else statement accordingly .
here is your example running
http://bl.ocks.org/radproject/31c48b1a7610e353d495

JavaScript induced style changes are not permanent

Okay, I change the appearance of links using JavaScript. When I change the content of a hard-coded link, it sticks in that the changed color and underlining remains when the cursor is not hovering above it. However, when the content of a DIV has been changed using JavaScript, the style changes do not stick.
Here is the HTML code:
<!doctype html>
<html>
<head>
<title>Bla bla</title>
<meta charset="UTF-8">
<link href="style/kim.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="scripts/Kim.js"></script>
</head>
<body>
<div class="wrapper">
<div class="main">
<div class="nav">
<div class="topNav">
<ul>
<li onClick="changeNav('design')">Design</li>
<li onClick="changeNav('code')">Programming</li>
<li onClick="changeNav('science')">Science</li>
<li onClick="changeNav('Kim')">Kim</li>
</ul>
</div>
<div id="subNav">
<script>changeNav("design");</script>
</div>
</div>
<div class="content">
<p id="mainText">Test</p>
</div>
</div>
</div>
</body>
</html>
Here is the JS code:
var topNavNames = ["design", "code", "science", "Kim"];
var subNavCode = ["<ul><li onClick=\"loadPHP('design/websites.php', 'sub0')\">Websites</li><li onClick=\"loadPHP('design/graphics.php', 'sub1')\">Graphics</li><li onClick=\"loadPHP('design/flash.php', 'sub2')\">Flash</li></ul>",
"<ul><li onClick=\"loadPHP('code/interactive.php', 'sub0')\">Interactive applets</li><li onClick=\"loadPHP('code/statistics.php', 'sub1')\">Statistics</li><li onClick=\"loadPHP('code/wings.php', 'sub2')\">Wings</li><li onClick=\"loadPHP('code/3D.php', 'sub3')\">3D</li></ul>",
"<ul><li onClick=\"loadPHP('science/3D.php', 'sub0')\">3D</li><li onClick=\"loadPHP('science/ssd.php', 'sub1')\">Sexual Size Dimorphism</li><li onClick=\"loadPHP('science/shape.php', 'sub2')\">Wing shape</li><li onClick=\"loadPHP('science/phylogenetics.php', 'sub3')\"><i>Drosophila</i> phylogenetics</li><li onClick=\"loadPHP('science/communitygenetics.php', 'sub4')\">Community Genetics</li><li onClick=\"loadPHP('science/biodiversity.php', 'sub5')\">Biodiversity</li></ul>",
"<ul><li onClick=\"loadPHP('Kim.php', 'sub0')\">Who is Kim?</li><li onClick=\"loadPHP('animals/horses.php', 'sub1')\">Horses</li><li onClick=\"loadPHP('animals/birds.php', 'sub2')\">Birds</li><li onClick=\"loadPHP('private/outdoors.php', 'sub3')\">Outdoors</li><li onClick=\"loadPHP('contact.php', 'sub4')\">Contact</li></ul>"];
function changeNav(target) {
for (var i = 0; i<topNavNames.length; i++) {
if (target == topNavNames[i]) {
document.getElementById("subNav").innerHTML=subNavCode[i];
document.getElementById(topNavNames[i]).style.color="#F7EDAA";
document.getElementById(topNavNames[i]).style.borderBottom="thin solid #F7EDAA";
}
else {
document.getElementById(topNavNames[i]).style.color="#EEE";
document.getElementById(topNavNames[i]).style.borderBottom="thin solid #111";
}
}
}
function loadPHP(url, target) {
for (var i = 0; i<10; i++) {
if(document.getElementById(target)!=null) {
if (("sub"+i) == target) {
document.getElementById(target).style.color="#F7EDAA";
document.getElementById(target).style.borderBottom="thin solid #F7EDAA";
}
else {
document.getElementById(target).style.color="#EEE";
document.getElementById(target).style.borderBottom="thin solid #111";
}
}
}
}
if I subsequently remove the:
else {
document.getElementById(target).style.color="#EEE";
document.getElementById(target).style.borderBottom="thin solid #111";
}
from the loadPHP function, it changes the style, but does not reset it when the next link is clicked.
I observed this behavior in FireFox, Internet Exploder and Chrome.
Added: CSS code:
body {
background-color: #111111;
color: #DDD;
font-family: "Gill Sans", "Gill Sans MT", "Myriad Pro", "DejaVu Sans Condensed", Helvetica, Arial, sans-serif;
}
.wrapper {
overflow: auto;
}
.banner {
float: left;
position: relative;
width: 100px;
}
.main {
position: relative;
width: 80%;
left: 25px;
font-size: 14px;
font-weight: normal;
}
a {
text-decoration: none;
color: #EEE;
}
a:hover {
border-bottom: thin solid #F7EDAA !important;
color: #F7EDAA !important;
}
.topNav {
height: 45px;
position: relative;
left: 100px;
font-size: large;
border: thin solid #111;
}
#subNav {
height: 45px;
position: relative;
left: 100px;
top: 2px;
border: thin solid #111;
}
.topNav li, #subNav li {
float: left;
margin: 10px 15px;
}
.topNav ul, #subNav ul {
list-style: none;
padding: 0px 0px;
margin: 0px 0px;
position: relative;
left: -100px;
}
.content {
position: relative;
left: 15px;
padding: 0px 0px;
margin: 0px 0px;
}
.content p {
padding: 5px 5px;
margin: 10px 15px;
left: -100px;
}
In my opinion you´re using the wrong technology to achieve your goal. What you need to do is to write your styles in a css stylesheet, and then add or remove classes to your elements using js if you want. (You can also do this through something called specificity, a little far ahead from the scope of your question)
Also think that if there is some bug in your script, or a third party script called in your page, JS may break and it won´t process your styling changes.
So, add the basic styling to your elements through css in the initial markup, so you will be sure that your elements will have always a basic styling, and then if you want use the equivalent to .addClass or removeClass jQuery methods.
In that way you will be always sure that your frontend will have always a safe styling, won´t break if js is not loaded, and separation of concerns will be properly implemented.
Regards.
I figured it out. The following code does not do the right thing:
function loadPHP(url, target) {
for (var i = 0; i<subNavNames.length; i++) {
if (target == subNavNames[i]){
document.getElementById(target).className="selected";
} else {
document.getElementById(target).className="notSelected";
}
}
While this code does produce the right result:
function loadPHP(url, target) {
for (var i = 0; i<subNavNames.length; i++) {
if (target == subNavNames[i]) {
document.getElementById(subNavNames[i]).className="selected";
} else {
document.getElementById(subNavNames[i]).className="notSelected";
}
}
The difference is that in the first example, and in the example of the original question, I use the variable passed on in the method (target), to find the element. In the second, I use the appropriate element from a array that I have added to the list. I am not sure WHY this behaves differently, but it does.

Categories