Adding more childs to a script - javascript

I have a cool script that works with two buttons. I need to add THREE more buttons as options for a total of FIVE altogether.
Does the whole script have to be re-written or could I just add more DIV classes? Not sure how to approch. Working for days on this...
Here is my link: http://jsfiddle.net/9cr4F/9/
HTML:
<div id="r6">
<div class="bx bx1">6</div>
<div id="sp"></div>
<div class="bx bx2">Gender</div>
<div id="sp"></div>
<div id="bxGender">
<input type="button" class="gnM" >
<div id="sp"></div>
<input type="button" class="gnF">
<div id="sp"></div>
<input class="req-string gender" id="gender" name="gender"></div>
</div>
CSS:
#r6 {
font-family: Verdana, Arial, Helvetica, sans-serif;
}
.bx {
height:60px;
line-height:60px;
float:left;
font-size:105%;
margin-top:15px;
color: #000;
background-color: #E8E8E8
}
.bx1 {
width:60px;
text-align:center
}
.bx2 {
width:175px;
padding-left:20px
}
#sp {
width: 15px;
height:60px;
float:left;
}
.gnM {
width:137px;
height: 60px;
background:#E8E8E8 url('http://www.41q.org/admin/img/male.png') 0px 0px no-repeat;
margin-top:0px;
padding: 0;
border: 0;
margin-left: 0px;
float: left;
outline: none;
text-align:center;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 105%;
font-style:normal;
color:#03F;
}
.gnF {
width:137px;
height: 60px;
background:#E8E8E8 url('http://www.41q.org/admin/img/female.png') 0px 0px no-repeat;
margin-top:0px;
padding: 0;
border: 0;
margin-left: 0px;
float: left;
outline: none;
text-align:center;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 105%;
font-style:normal;
color:#03F;
}
#r6 #bxGender .button-toggle-on {
background-position: 0 -120px
}
#bxGender {
width:486px;
height:60px;
float:left;
margin-top:15px
}
#r6:hover div.bx, #r6:hover input {background-color: #A9A9A9; cursor:pointer}
#r6:hover .gnM, #r6:hover .gnF {background-position: 0 -60px; cursor:pointer}
jQuery:
$(function() {
var $buttons = $("input[type='button']");
$buttons.click(function() {
$(this).parent().siblings('.bx, #bxGender .gender').css({'background':'#2F2F2F','color':'#fff'});
$buttons.not(this).removeClass('button-toggle-on');
$(this).toggleClass('button-toggle-on').attr('style','');
var varval = '';
if ($(this).hasClass('button-toggle-on')) {
varval = $(this).hasClass('gnF') ? 'Female' : 'Male';
$(this).siblings('input[type="button"]').css('background-position','0 -180px');
}
else {
$(this).siblings('input[type="button"]').attr('style','');
$(this).parent().siblings('.bx').attr('style','');
}
$("#gender").val(varval);
});
});

First thing you need is a markup to validate, at the moment it is not, IDs in a document must be UNIQUE so when you do
<div id="sp"></div>
you should do
<div class="sp"></div>
and try to get the clone nicely nested, even if it copies badly in here sometimes it helps to even have just few spaces here and there :)
In your CSS don't repeat the same properties if it applies to multiple elements, for example I restructured your gnF and gnM class, so all the properties are together and only the background image property is seperate.
.gnM,
.gnF,
.gnA {
background:#E8E8E8 0px 0px no-repeat;
text-indent:-10000px;
width:137px;
height: 60px;
margin-top:0px;
padding: 0;
border: 0;
margin-left: 0px;
float: left;
outline: none;
text-align:center;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 105%;
font-style:normal;
color:#03F;
}
.gnA {
background-image:url('http://www.41q.org/admin/img/alien.png');
}
.gnM {
background-image:url('http://www.41q.org/admin/img/male.png');
}
.gnF {
background-image:url('http://www.41q.org/admin/img/female.png');
}
You can simplify the jquery side by using the value attribute on your button, if you set a text-indent then the text wont show, and then you can simply retrieve the value using $(this).val();
$(function() {
var $buttons = $("input[type='button']"),
varval;
$buttons.click(function() {
// this should be done using a class to keep the js cleaner
$(this).parent().siblings('.bx, #bxGender .gender').css({
'background': '#2F2F2F',
'color': '#fff'
});
$buttons.removeClass('button-toggle-on');
$(this).addClass('button-toggle-on');
$("#gender").val($(this).val());
});
});​
This gives you a lot more flexibility as you can have as many button as you want but if you are building a form with multiple rows, as it seems, I would suggest also using a class for the input that contains the result and modify the value assignment so that it grabs the closest result input and update that, so that way it works for all rows.
Here is the modified fiddle http://jsfiddle.net/9cr4F/14/ - the third buttons styling is screwed of course but I'm sure it gives you what you need :)
Edited: Optimized CSS a bit more
Edited 2: Optimized the jquery code and move the background positioning to the class button-toggle-on as it is on when the background position need to be applied.

Related

Trying to make two functions requiring same value but in two input types (div and text)

I am trying to combine two functions into one in an interface. I have looked up div to input pages and yet to find the right answer.
The first function is used to construct a formula which translates it into a string format that is acceptable to another service.
The second function allows me to use an #mention type jQuery which triggers a list to select from as I type when I add a # symbol in the text.
The problem I have is that the first function only works with a form input "text" and the second function only works if I make the input a div with contenteditable="true".
I have tried to make either function work with the properties of the other and its just no good.
What I think I want is a way of copying the value of the text box into the form input box when I click on Refresh Console button.
Additionally, I only want to show one of them, the one I type in. So that means I want to use the form input field but have it hidden.
Here's my code that has two independently working functions. Where it says "type an at sign here" type an # and you will see the options. The input box which says "24 + 6 / 10 * 100" is controlling a function where the results are available in the console as 24|6|add|10|divide|100|multiply which is the expected result.
What I want to do is create a formula in the div text box like #net_value + #tax_value which are selectable at each point you add an at sign.
EDIT I have corrected some fundamental issues with the HTML but still have the same issue with a new one, box displays an extra box that I cannot get rid of no matter what I do.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script
src="https://cdn.jsdelivr.net/npm/jquery#3.4.1/dist/jquery.min.js">
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/ichord/At.js#master/dist/css/jquery.atwho.min.css">
<script src="https://cdn.jsdelivr.net/gh/ichord/At.js#master/dist/js/jquery.atwho.min.js"></script>
<link rel="stylesheet" href="dynamic_table.css">
<title>BODMAS Translation</title><br>
<h1>BODMAS Translation</h1><br><br>
<input type = "text" id="f_input" name="formula" value="24 + 6 / 10 * 100">
<br><br>
<button onclick="myFunction()">Refresh Console</button><br><br>
<div id="enter_formula" class="text_input" contenteditable="true">Type an at sign here </div><br>
<script>
function myFunction() {
var operators = {
'*': 'multiply',
'/': 'divide',
'+': 'add',
'-': 'subtract'
},
string = document.getElementById("f_input").value,
result = string.replace(/\s+([^\s]+)\s+([^\s]+)/g, (_, o, v) => `|${v}|${operators[o]}`);
console.log(result);
};
</script>
<script>
$('#enter_formula').atwho({
at: "#",
data: ['input.net_value', 'input.tax_value', 'output.description']
});
</script>
</html>
Also including the css dynamic_table.css
table {
padding-inline: 15px;
padding-left: 10px;
border-color: rgb(182, 204, 243);
border-collapse: collapse;
border-style: hidden;
border-bottom: indianred;
font-family: Arial, Helvetica, sans-serif;
font-size: medium;
table-layout: fixed;
}
t1 {
font-family: Arial, Helvetica, sans-serif;
font-size: larger;
font-weight: bold;
}
thead {
font-family: Arial, Helvetica, sans-serif;
font-size: small;
background-color: rgb(182, 204, 243);
}
input {
width: 600px;
height: 30px;
padding: 5px;
}
div {
font-family: Arial, Helvetica, sans-serif;
font-size: small;
max-width: 600px;
height: 40px;
padding: 5px;
border: 1px solid rgb(170, 175, 163);
vertical-align: middle;
}
tbody {
font-size: small;
text-align: center;
}
.notfirst:hover {background-color: #f5f5f5;}
td {
height: 30px;
vertical-align: middle;
column-span: 2;
padding-left: 10px;
padding-right: 10px;
}
button {
border-radius: 8px;
height: 40px;
width: 100px;
background-color: rgb(50, 192, 197);
}

Angular example from the web not working

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>

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.

Optimize jQuery code

I've written this jQuery code that fades in a overlay with some links over an image. What i found out is that it is painfully slow when I add like 10 of these images. I would really appreciate some tips and tricks on how to make this code faster.
If you have some tips for my HTML and CSS that would be great too ;)
jQuery code
$(document).ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").hover(
function () {
$(this).children(".download").fadeTo("fast", 1);
$(this).children(".hud").fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
All the code
<style type="text/css">
a:active {
outline:none;
}
:focus {
-moz-outline-style:none;
}
img {
border: none;
}
#backgrounds {
font: 82.5% "Lucida Grande", Lucida, Verdana, sans-serif;
margin: 50px 0 0 0;
padding: 0;
width: 585px;
}
.thumb {
margin: 5px;
position: relative;
float: left;
}
.thumb img {
background: #fff;
border: solid 1px #ccc;
padding: 4px;
}
.thumb div {
display: none;
}
.thumb .download {
color: #fff;
position: absolute;
top: 0;
left: 0;
z-index: 999;
padding: 0 10px;
}
.thumb .download h3 {
font-size: 14px;
margin-bottom: 10px;
margin-top: 13px;
text-align: center;
}
.thumb .download a {
font-size: 11px;
color: #fff;
text-decoration: none;
font-weight: bold;
line-height: 16px;
}
.thumb .download a:hover {
text-decoration: underline;
}
.thumb .download .left, .thumb .download .right {
width: 44%;
margin: 0;
padding: 4px;
}
.thumb .download .left {
float: left;
text-align: right;
}
.thumb .download .right {
float: right;
text-align: left;
}
.thumb img, .thumb .hud {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.thumb .hud {
width: 100%;
height: 110px;
position: absolute;
top: 0;
left: 0;
background: #000;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").hover(
function () {
$(this).children(".download").fadeTo("fast", 1);
$(this).children(".hud").fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
</script>
<div id="backgrounds">
<div class="thumb">
<div class="download">
<h3>Download wallpaper</h3>
<p class="left">
1024x768
1280x800
1280x1024
</p>
<p class="right">
1440x900
1680x1050
1920x1200
</p>
</div>
<div class="hud"></div>
<img alt="image" src="thumb.jpg"/>
</div>
</div>
I got it to respond a little better by simply changing the following within the hover(..):
function () {
$(".download", this).fadeTo("fast", 1);
$(".hud", this).fadeTo("fast", 0.7);
},
function () {
$(".download, .hud", this).fadeTo("fast", 0);
}
The biggest difference comes from only applying the hoverout effect to the event target, no need to reapply to all your divs on the page.
I've put your code into a test page and to be perfectly honest, even with thirty or so .thumb divs it seemed ok - certainly responsive enough to use from my end. Sliding the mouse over a bunch of them means I have to wait for the rollover effect to go through them all which takes a while until it gets to the one I've actually stopped on, but surely that was what you wanted given that you're using 'hover' rather than 'click' (which would certainly remove any speed issues).
I'm not using actual images in my test page, just getting the alt text, so my best current guess would be to make sure all images you're loading are as small filesize as you can possibly make them.
Pre-Select MORE
Good job preselecting the div. Try this way so that it pre-selects the fade in elements as well instead of doing it on hover:
$().ready(function() {
var div = $(".thumb").find("div");
div.fadeTo(0, 0);
div.css("display","block");
$(".thumb").each(function() {
var download = $(this).children(".download");
var hud = $(this).children(".hud");
$(this).hover(
function () {
download.fadeTo("fast", 1);
hud.fadeTo("fast", 0.7);
},
function () {
div.fadeTo("fast", 0);
}
);
});
});
try removing the
:focus {
-moz-outline-style:none;
}
and see what happens

Categories