Archive for the ‘JavaScript’ Category

NodeJS ReactJS, NOT using Isomorphic-fetch, using jQuery JSONP GET -> Oracle Service Cloud Article Feedback ci/ajaxCustom Endpoint

Friday, June 23rd, 2017

app.js

'use strict';

const compression = require('compression');
const express = require('express');
const next = require('next');
const path = require('path');
const fetch = require('isomorphic-fetch');

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const auth = '...';
const site = 'help-*-*';
const server = express();

class GetHelp {
constructor() {

this.initApp();
}

/*
Start express application and express healthcheck.
*/
initApp() {
app.prepare().then(() => {

/*
* API Server
*/

server.get('/api/search/:searchTerm', (req, res, next) => {
const searchTerm = req.params.searchTerm;
var endpoint = `services/rest/connect/v1.3/analyticsReportResults`;

fetch(
`https://${auth}@${site}.....com/${endpoint}`, {
method: 'POST',
mode: 'no-cors',
body: JSON.stringify({
"id": 178394,
"filters": [{
"name": "os_search",
"values": [
searchTerm
]
}]
})
})
.then(function(res) { return res.json(); })
.then(function(data) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ article: data }));
});
});

server.get('/api/article/:articleId', (req, res, next) => {
const articleId = req.params.articleId;
var endpoint = "";
if (parseInt(articleId)) {
endpoint = `/services/rest/connect/v1.3/answers/${articleId}/?fields=solution,summary`;
} else {
endpoint = `/services/rest/connect/v1.3/queryResults/?query=select summary,solution from answers where customFields.c.slug='${articleId}'and customFields.c.lang_id=2035 and language=1 and AccessLevels.NamedIDList.ID=11`;
}

fetch(
`https://${auth}@${site}.....com/${endpoint}`, {
method: 'GET',
mode: 'no-cors',
})
.then(function(res) { return res.json(); })
.then(function(data) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ article: data }));
});
});

var endpoint = "services/rest/connect/v1.3/queryResults/?query=select lookupName,value from messageBases ";
endpoint += "where lookupName in (" + msgToGet + ")";

fetch(
`https://${auth}@${site}.....com/${endpoint}`, {
method: 'GET',
mode: 'no-cors',
})
.then(function(res) { return res.json(); })
.then(function(data) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ messageBase: data }));
});
});

/*
* APP Routes
*/

server.get('/search/:searchTerm/page/:page', (req, res) => {
const params = { searchTerm: req.params.searchTerm, page: req.params.page }
return app.render(req, res, '/search', params);
});

server.get('/article/:articleId', (req, res) => {
const params = { articleId: req.params.articleId }
return app.render(req, res, '/article', params);
});

server.get('*', (req, res) => {
return handle(req, res);
});

server.listen(8080, 'local-www....dev.com', () => {
this.initHealthcheck();
});
});
}

}

module.exports = new GetHelp();

/components/StarRating.js

</pre></pre>
import React from 'react';

import Link from '../components/Link';

import Router from 'next/router'

import 'isomorphic-fetch';

import Modal from 'react-modal';

&nbsp;

&nbsp;

const site = 'help-en-us';

const customStyles = {

content : {

top: '50%',

left: '50%',

right: 'auto',

bottom: 'auto',

marginRight: '-50%',

transform: 'translate(-50%, -50%)'

}

};

&nbsp;

&nbsp;

export default class extends React.Component {

constructor(props) {

super(props);

this.state = {

starRating: 0,

articleId: this.props.articleId,

thankYou: false,

showStars: true

};

&nbsp;

&nbsp;

this.handleStar = this.handleStar.bind(this);

this.submitRating = this.submitRating.bind(this);

this.getToken = this.getToken.bind(this);

this.onKeyPress = this.onKeyPress.bind(this);

this.openModal = this.openModal.bind(this);

this.afterOpenModal = this.afterOpenModal.bind(this);

this.closeModal = this.closeModal.bind(this);

this.cancelModal = this.cancelModal.bind(this);

this.submitAnswerFeedback = this.submitAnswerFeedback.bind(this);

this.getToken = this.getToken.bind(this);

}

&nbsp;

&nbsp;

async submitRating(rating) {

let result = await $.ajax({

url: `http://${site}.....com/ci/ajaxCustom/submitAnswerRating`,

data: `a_id=${this.props.articleId}&amp;amp;rate=${rating}&amp;amp;options_count=5`,

dataType: 'jsonp',

jsonpCallback: 'submitAnswerRating',

success: function(response){

console.log(response.submitted);

}

});

let flag = await result;

return flag

};

&nbsp;

&nbsp;

async getToken(rating){

let result = await $.ajax({

url: `http://${site}.....com/ci/ajaxCustom/getNewFormToken`,

data: `formToken=${Math.random().toString(36).substr(2)}`,

dataType: 'jsonp',

jsonpCallback: 'getNewFormToken',

success: function(response){

//console.log(typeof(response.newToken));

return response;

}

});

let token = await result;

return token

};

&nbsp;

&nbsp;

async submitAnswerFeedback(){

let a_id = this.props.articleId;

let rating = this.state.starRating;

let feedbackMessageValue = this.state.feedbackMessageValue;

let token = this.state.token;

console.log('sAF: ' + token);

&nbsp;

&nbsp;

let result = await $.ajax({

url: `http://${site}.....com/ci/ajaxCustom/submitAnswerFeedback`,

data: `a_id=${a_id}&amp;amp;rate=${rating}&amp;amp;message=${feedbackMessageValue}&amp;amp;f_tok=${token}`,

dataType: 'jsonp',

jsonpCallback: 'submitAnswerFeedback',

success: function(response){

console.log(response);

}

});

&nbsp;

&nbsp;

let message = await result;

this.closeModal();

&nbsp;

&nbsp;

return message

};

&nbsp;

&nbsp;

async handleStar(rating){

// submit the star rating clicked

let ratingSubmitted = await this.submitRating(rating);

if(rating >= 3){

// submitted, and done

this.setState({

thankYou: true,

starRating: rating,

ratingSubmitted: ratingSubmitted,

showStars: false

})

} else {

// less than 3, so get a token, and open popup

let token = await this.getToken(rating);

console.log('obj: ' + token.newToken);

console.log(typeof(token.newToken));

this.openModal();

this.setState({

thankYou: true,

starRating: rating,

ratingSubmitted: ratingSubmitted,

token: token.newToken,

showStars: false

})

}

}

&nbsp;

&nbsp;

onKeyPress(e) {

let feedbackMessageValue = e.target.value;

}

&nbsp;

&nbsp;

onChange(e) {

let feedbackMessageValue = e.target.value;

this.setState({

feedbackMessageValue: feedbackMessageValue

});

}

&nbsp;

&nbsp;

openModal() {

this.setState({

modalIsOpen: true

});

}

&nbsp;

&nbsp;

afterOpenModal() {

// references are now sync'd and can be accessed.

this.subtitle.style.color = '#f00';

}

&nbsp;

&nbsp;

closeModal() {

this.setState({

modalIsOpen: false

});

}

&nbsp;

&nbsp;

cancelModal() {

this.setState({

modalIsOpen: false,

showStars: true,

thankYou: false

})

}

&nbsp;

&nbsp;

render () {

const stars = [1,2,3,4,5];

const starRating = this.state.starRating;

const thankYou = this.state.thankYou;

const showStars = this.state.showStars;

&nbsp;

&nbsp;

return (

&nbsp;

&nbsp;

<div className="box">

<div className="answerFeedback">

{!thankYou ? <div className="title">Please rate this article:</div> : ""}

{showStars ? (  <div className="starsBox">

{

stars.map((star) => {

return(

<span

key={star}

className={`g72-star ${star<=starRating?'selectedStar':''}`}

onClick={(e) => this.handleStar(star)}>

</span>

)

})

}

</div>) : (<span></span>)

}

{thankYou ? <div className="thankYou">Thank you for your feedback!</div> : ""}

<div> {

//<button onClick={this.openModal}>Open Modal</button> }

<Modal

isOpen={this.state.modalIsOpen}

onAfterOpen={this.afterOpenModal}

onRequestClose={this.closeModal}

style={customStyles}

contentLabel="Example Modal">

&nbsp;

<h2 ref = { subtitle => this.subtitle = subtitle }>Provide Additional Information</h2>

<div className = "submittedMessage">Your rating has been submitted, please tell us how we can make this answer more useful.</div>

<div className = "faqQuestion">FAQ Feedback – How can we improve this answer? *</div>

<textarea

className = "feedbackMessage"

id = "feedbackMessage"

name = "feedbackMessage"

rows = "4"

cols = "50"

value = { this.state.feedbackMessageValue }

onKeyPress = { (e) => this.onKeyPress(e) }

onChange={(e) => this.onChange(e)}></textarea>

<div className="formButtons">

<button onClick = { this.submitAnswerFeedback } className="submitButton">Submit</button>

<button onClick = { this.cancelModal } className="cancelButton">Cancel</button>

</div>

&nbsp;

&nbsp;

</Modal>

</div>

</div>

<style jsx>{`

.answerFeedback .title {

font-weigth: bold;

}

.answerFeedback .g72-star {

font-size: 1.5em;

margin: 5px;

cursor: pointer;

color: #6d6b6b;

}

.answerFeedback .g72-star:hover, .selectedStar{

color: rgb(251, 224, 0) !important;

}

.starsBox {

background: #a09e9e;

border-radius: 10px;

padding: 0 10px;

width: 170px;

text-align: center;

}

.feedbackMessage {

border: 1px solid;

margin: 10px 10px 10px 0;

padding: 10px;

width: 100%;

}

.formButtons {

text-align: right;

}

.submitButton, .cancelButton {

width: 100%;

margin: 0;

padding: 10px;

font-weight: bold;

color: white;

text-transform: uppercase;

border-radius: 3px;

text-align: center;

text-decoration: none;

}

.submitButton {

background-color: rgba(250, 84, 0, 1);

}

.submitButton:hover {

background-color: #666;

}

.cancelButton {

background-color: rgb(153, 153, 153);

}

.cancelButton:hover {

background-color: #666;

}

.submitbutton:hover {

&nbsp;

&nbsp;

}

`}</style>

</div>

);

}

}
<pre>
Oracle AjaxCustom Service endpoint
function submitAnswerRating()
 {
 $answerID = $this-&amp;gt;input-&amp;gt;get('a_id');
 $rating = $this-&amp;gt;input-&amp;gt;get('rate');
 $scale = $this-&amp;gt;input-&amp;gt;get('options_count');
 if($answerID){
 if($this-&amp;gt;model('Answer')-&amp;gt;rate($answerID, $rating, $scale)){
 print "submitAnswerRating({'submitted':'true'})";
 }else{
 print "submitAnswerRating({'submitted':'false'})";
 }
 }
 }
 
 function getNewFormToken()
 {
 if($formToken = $this-&amp;gt;input-&amp;gt;get('formToken'))
 {
 $newToken = Framework::createTokenWithExpiration(0, false);
 print "getNewFormToken({'newToken':'" . $newToken . "'})";
 }
 }
 
 function submitAnswerFeedback()
 {
 AbuseDetection::check();
 $answerID = $this-&gt;input-&gt;get('a_id');
 if($answerID === 'null')
 $answerID = null;
 $rate = $this-&gt;input-&gt;get('rate');
 $message = $this-&gt;input-&gt;get('message');
 $givenEmail = '...@....com';
 $threshold = 3;
 $optionsCount = 5;
 $formToken = $this-&gt;input-&gt;get('f_tok');
 $incidentResult = $this-&gt;model('Incident')-&gt;submitFeedback($answerID, $rate, $threshold, null, $message, $givenEmail, $optionsCount);
 if($incidentResult-&gt;result){
 print "submitAnswerFeedback({'ID':'" . $incidentResult-&gt;result-&gt;ID . "'})";
 //$this-&gt;_renderJSON(array('ID' =&gt; $incidentResult-&gt;result-&gt;ID));
 }else{
 if($incidentResult-&gt;error){
 print "submitAnswerFeedback({'error 2':'" . $incidentResult-&gt;error-&gt;externalMessage . "'})";
 }
 }

test return values of user’s browser

Tuesday, May 10th, 2016
var $temp = $('<div style="background-color:#ffffff"/>').appendTo('body');
var thisBrowserWhite = $temp.css('background-color');
$temp.remove();
console.log(thisBrowserWhite);

add unique to Javascript Array prototype

Tuesday, May 10th, 2016
Array.prototype.unique = function() {
    var a = this.concat();
    for(var i=0; i<a.length; ++i) {
        for(var j=i+1; j<a.length; ++j) {
            if(a[i] === a[j])
                a.splice(j--, 1);
        }
    }
    return a;
};

Google maps, mySQL locations, PHP service

Wednesday, May 4th, 2016

HTML:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <link rel="stylesheet" href="dealers.css">
</head>
    <body>
        <div class="row mapSection">
            <div class="col-xs-12">

                <div id="map"></div>
                <div id="panel">
                    <div id="entryRow">
                        <div><select id="locationSelect" style="width:100%;visibility:hidden"></select></div>
                        <input type="text" id="addressInput" />
                        <select id="radiusSelect">
                            <option value="5" selected>5 miles</option>
                            <option value="25" selected>25 miles</option>
                            <option value="100">100 miles</option>
                            <option value="200">200 miles</option>
                            <option value="500">500 miles</option>
                        </select>
                        <input type="text" id="find" value="Search"/>
                        <input type="button" id="refresh" value="redo Search"/>
                    </div>
                    <ul class="resultDealers">
                    </ul>
                </div>

            </div>
        </div>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
        <script src="https://maps.googleapis.com/maps/api/js?key=***YOUR*KEY*HERE***" type="text/javascript"></script>
        <script type="text/javascript" src="Maps.js"></script>
    </body>
</html>

CSS:

body {
  font-family: sans-serif;
  margin: 0px;
  padding: 0px;
}
#map,
#panel {
  height: 500px;
  float: left;
}
#map {
  width: 60%;
}
#entryRow {
  margin: 0 0 0 15px;
}
#panel {
  width: 40%;
}
.resultDealers {
  padding: 0;
  margin: 15px;
  overflow: scroll;
  height: 420px;
}
.resultDealers li {
  list-style-type: none;
  border-left: 1px solid;
  border-top: 1px solid;
  border-right: 1px solid;
  padding: 10px;
}
.resultDealers li:last-child {
  border-bottom: 1px solid;
}
.highlightDealer {
  background: #E8E8E8;
}
.markerBox {
  cursor: pointer;
}
.markerBox:hover {
  background: #E3F4F9;
}
#panel .feature-filter label {
  width: 130px;
}
p.attribution,
p.attribution a {
  color: #666;
}
#find {
  background: #DEDCDC;
  border: 1px solid gray;
  width: 65px;
  padding: 2px;
  text-align: center;
  font-weight: bold;
  cursor: pointer;
  margin-left: 15px;
}
#find:hover {
  background: #F9F4F4;
}
#radiusSelect {
  margin-left: 15px;
}
#addressInput {
  float: left;
  margin-left: 5px;
  padding-left: 10px;
  width: 65px;
}
#locationSelect {
  margin: 10px 5px;
  width: 95% !important;
}

JavaScript:

/* ---------  Start Maps.js  --------- */

Maps Module
//Usage: Maps.init();

Maps = (function ( window, google ) {

	var map,
		markers = [],
		infoWindow,
		locationSelect;

	var load = function load () {
			map = new google.maps.Map(document.getElementById("map"), {
				center: new google.maps.LatLng(40, -100),
				zoom: 4,
				mapTypeId: 'roadmap',
				// scrollWheel: false,
				// zoomControl: false,
				streetViewControl: false,
				rotateControl: false,
				fullscreenControl: false,
				navigationControl: false,
				scaleControl: false,
				// draggable: false,
				mapTypeControl: false,
				mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
		});
		infoWindow = new google.maps.InfoWindow();

		locationSelect = document.getElementById("locationSelect");
		locationSelect.onchange = function() {
			var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
			if (markerNum != "none"){
				google.maps.event.trigger(markers[markerNum], 'click');
			}
		};

		refreshMap();

		google.maps.event.addListener(map, 'zoom_changed', function() {
			//$('#radiusSelect option:selected').next().attr('selected', 'selected');
			//console.log(map.getCenter());
			//searchLocationsNear (map.getCenter());
		});

	}

	var bindInfoWindow = function bindInfoWindow ( marker, map, infoWindow, html ) {
      google.maps.event.addListener(marker, 'click', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);
      });
    }

    var refreshMap = function refreshMap () {
    	if(navigator.geolocation) {
			navigator.geolocation.getCurrentPosition(function(position) {

				var latLng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);

				var geocoder = new google.maps.Geocoder();

				geocoder.geocode({ 'latLng': latLng}, function (results, status) {
					if (status == google.maps.GeocoderStatus.OK) {

						for ( var j = 0; j < results[0].address_components.length; j++ ) {
							for ( var k = 0; k < results[0].address_components[j].types.length; k++ ) {
								if ( results[0].address_components[j].types[k] == "postal_code" ) {
									zipcode = results[0].address_components[j].short_name;
								}
							}
						}

						document.getElementById("addressInput").value = zipcode;
						searchLocations();
					} else {
						console.log("Geocoding failed: " + status);
					}
				});
			});
		}
	}

	var downloadUrl = function downloadUrl ( url, callback ) {
		var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;
		request.onreadystatechange = function() {
			if ( request.readyState == 4 ) {
				request.onreadystatechange = doNothing;
				callback(request.responseText, request.status);
			}
		};

		request.open('GET', url, true);
		request.send(null);
	}

	var searchLocations = function searchLocations () {
		var address = document.getElementById("addressInput").value;
		var geocoder = new google.maps.Geocoder();
		geocoder.geocode({address: address}, function(results, status) {
			if (status == google.maps.GeocoderStatus.OK) {
	  			searchLocationsNear(results[0].geometry.location);
			} else {
	  			alert(address + ' not found');
			}
		});
	}

	var clearLocations = function clearLocations() {
		infoWindow.close();
		for (var i = 0; i < markers.length; i++) {
			markers[i].setMap(null);
		}
		markers.length = 0;

		locationSelect.innerHTML = "";
		var option = document.createElement("option");
		option.value = "none";
		option.innerHTML = "See all results:";
		locationSelect.appendChild(option);
	}

	var searchLocationsNear = function searchLocationsNear ( center ) {
		clearLocations();

		var radius = document.getElementById('radiusSelect').value;
		var searchUrl = '/dealers.php?lat=' + center.lat() + '&lng=' +  center.lng() + '&radius=' + radius;
		downloadUrl( searchUrl, function(data) {
			var xml = parseXml(data);
			var markerNodes = xml.documentElement.getElementsByTagName("marker");
			var bounds = new google.maps.LatLngBounds();
			for (var i = 0; i < markerNodes.length; i++) {
				var id = markerNodes[i].getAttribute("id");
				var name = markerNodes[i].getAttribute("name");
				var address = markerNodes[i].getAttribute("address");
				var city = markerNodes[i].getAttribute("city");
				var state = markerNodes[i].getAttribute("state");
				var zip = markerNodes[i].getAttribute("zip");
				var url = markerNodes[i].getAttribute("url");
				var email = markerNodes[i].getAttribute("email");
				var distance = parseFloat(markerNodes[i].getAttribute("distance"));
				var latlng = new google.maps.LatLng(
					parseFloat(markerNodes[i].getAttribute("lat")),
					parseFloat(markerNodes[i].getAttribute("lng")));

				createOption(name, distance, i);
				createMarker(id, latlng, name, address, city, state, zip, url, email);
				bounds.extend(latlng);
			}
			map.fitBounds(bounds);
			locationSelect.style.visibility = "visible";
			locationSelect.onchange = function() {
			 var markerNum = locationSelect.options[locationSelect.selectedIndex].value;
			 google.maps.event.trigger(markers[markerNum], 'click');
			};
		});
	}

	var createMarker = function createMarker ( id, latlng, name, address, city, state, zip, url, email ) {
		var html = "<div class='marker-" + id + "'><b>" + name + "</b> <br/>" + address +  "<br/>" + city + " " + state + ", " + zip + "<br />" + url + "<br /><a href='mailto:" + email + "'>" + email + "</a></div>";
		var marker = new google.maps.Marker({
			map: map,
			position: latlng
		});
		google.maps.event.addListener(marker, 'click', function() {
			//infoWindow.setContent(html);
			//infoWindow.open(map, marker);
			$("li[class*='marker-']").removeClass('highlightDealer');
			$("li.marker-" + id).addClass('highlightDealer');
			window.location.href = "#marker-"+ id;
			window.scrollTo(0, 0);

			map.setZoom(16);
			map.setCenter(marker.getPosition());
		});
		markers.push(marker);

		$("#panel ul").append("<li class='markerBox marker-" + id + "'><a name='marker-" + id + "'></a><b>" + name + "</b><br/>" + address +  "<br/>" + city + " " + state + ", " + zip + "<br />" + url + "<br /><a href='mailto:" + email + "'>" + email + "</a></li>");
		$('.marker-' + id).on('click', function() {
			$("li[class*='marker-']").removeClass('highlightDealer');
			$("li.marker-" + id).addClass('highlightDealer');
			map.setZoom(16);
			map.setCenter(marker.getPosition());
		});
	}

	var createOption = function createOption ( name, distance, num ) {
		var option = document.createElement("option");
		option.value = num;
		option.innerHTML = name + "(" + distance.toFixed(1) + ")";
		locationSelect.appendChild(option);
	}

	var parseXml = function parseXml(str) {
		if (window.ActiveXObject) {
			var doc = new ActiveXObject('Microsoft.XMLDOM');
			doc.loadXML(str);
			return doc;
		} else if (window.DOMParser) {
			return (new DOMParser).parseFromString(str, 'text/xml');
		}
	}

    function doNothing() {}

	$('#find').on('click', function() {
		$('#panel ul').empty();
		searchLocations();
	});
	$('#addressInput').on('click', function () {
		$(this).val('');
	});
	$('#radiusSelect').on('change', function () {
		$('#panel ul').empty();
		searchLocations();
	});
	$('#refresh').on('click', function () {
		var bounds = map.getBounds();
		var ne = bounds.getNorthEast(); // LatLng of the north-east corner
		var sw = bounds.getSouthWest(); // LatLng of the south-west corder

		var nw = new google.maps.LatLng(ne.lat(), sw.lng());
		var se = new google.maps.LatLng(sw.lat(), ne.lng());
		console.log('nw: ' + nw);
		console.log('se: ' + se);
		//searchLocationsNear();
		//searchLocations();
	});

	return {
		load: load
	}

})( window, google );

$(function(){
    loadModules.start();
})

var loadModules = loadModules || {};
loadModules.start = function(){
    // Maps module init
    Maps.load();
};
/* ---------  End Maps.js --------- */

PHP:

<?php
    header("Access-Control-Allow-Origin: *");
    $servername = "***Your*DB*URL***";
    $username = "***Your*DB*USERNAME***";
    $password = "***Your*DB*PASS***";
    $dbname = "***Your*DB*NAME***";

    // Get parameters from URL
    $center_lat = $_GET["lat"];
    $center_lng = $_GET["lng"];
    $radius = $_GET["radius"];

    // Start XML file, create parent node
    $dom = new DOMDocument("1.0");
    $node = $dom->createElement("markers");
    $parnode = $dom->appendChild($node);

    // Opens a connection to a mySQL server
    $connection=mysql_connect ($servername, $username, $password);
    if (!$connection) {
      die("Not connected : " . mysql_error());
    }

    // Set the active mySQL database
    $db_selected = mysql_select_db($dbname, $connection);
    if (!$db_selected) {
      die ("Can\'t use db : " . mysql_error());
    }

    // Search the rows in the markers table
    $query = sprintf("SELECT id, name, address, city, state, zip, url, email, lat, lng, ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance FROM dealers HAVING distance < '%s' ORDER BY distance LIMIT 0 , 20",
      mysql_real_escape_string($center_lat),
      mysql_real_escape_string($center_lng),
      mysql_real_escape_string($center_lat),
      mysql_real_escape_string($radius));
    $result = mysql_query($query);

    $result = mysql_query($query);
    if (!$result) {
      die("Invalid query: " . mysql_error());
    }

    header("Content-type: text/xml");

    // Iterate through the rows, adding XML nodes for each
    while ($row = @mysql_fetch_assoc($result)){
        $node = $dom->createElement("marker");
        $newnode = $parnode->appendChild($node);
        $newnode->setAttribute("id", $row['id']);
        $newnode->setAttribute("name", $row['name']);
        $newnode->setAttribute("address", $row['address']);
        $newnode->setAttribute("city", $row['city']);
        $newnode->setAttribute("state", $row['state']);
        $newnode->setAttribute("zip", $row['zip']);
        $newnode->setAttribute("url", $row['url']);
        $newnode->setAttribute("email", $row['email']);
        $newnode->setAttribute("lat", $row['lat']);
        $newnode->setAttribute("lng", $row['lng']);
        $newnode->setAttribute("distance", $row['distance']);
    }

    echo $dom->saveXML();

?>

Styling radio buttons

Monday, December 21st, 2015

Hide/replace radio buttons

CSS:

[type="radio"] {
  border: 0; 
  clip: rect(0 0 0 0); 
  height: 1px; margin: -1px; 
  overflow: hidden; 
  padding: 0; 
  position: absolute; 
  width: 1px;
}

[type="radio"] + span {
  display: block;
}

/* the basic, unchecked style */
[type="radio"] + span:before {
  content: '';
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.25em;
  border-radius: .5em;
  border: 0.15em solid @base-gray-medium;
  box-shadow: 0 0 0 0.1em @base-gray-medium;
  margin-right: 0.75em;
  transition: 0.5s ease all;
}

/* the checked style using the :checked pseudo class */
[type="radio"]:checked + span:before {
  background: red;
  box-shadow: 0 0 0 0.1em @base-gray-medium;
}

/* never forget focus styling */
[type="radio"]:focus + span:after {
  content: '\0020\2190';
  font-size: 1.5em;
  line-height: 1;
  vertical-align: -0.125em;
}

Handlebars template markup:

<script id="dealer-list-template" type="text/x-handlebars-template">
	<label for="dealer{{id}}" class="col-xs-10 dealerItem">
		<input type="radio" value="{{title}}" name="dealers" id="dealer{{id}}">
			<span class="dealerTitle">{{title}}</span>
			<span class="dealerAddress">{{address}}</span>
	</label>
	<div class="col-xs-2 distance">{{distance}}</div>
</script>

Javascript Module of jQuery extensions, example: animateRotate

Wednesday, November 25th, 2015
/* ---------  Start jquery.extensions.module.js  --------- */

// jquery extensions Module

(function ( $ ) {

	$.fn.animateRotate = function(angle, duration, easing, complete) {
		var args = $.speed(duration, easing, complete);
		var step = args.step;
		return $(this).each(function(i, e) {
		   	args.complete = $.proxy(args.complete, e);
		    args.step = function(now) {
		    	$.style(e, 'transform', 'rotate(' + now + 'deg)');
		    	if (step) return step.apply(e, arguments);
		    };

		    $({deg: 0}).animate({deg: angle}, args);
		});
	}

// method/extension #2 goes here, and so on...

})( window.jQuery );

/* ---------  End jquery.extensions.module.js --------- */

Google Maps API v3 load array of locations, detect ip and zoom, generate list by distance to locations

Friday, October 23rd, 2015

In the template or HTML:

<div id="container">
<div class="row mapSubNav">
<div class="col-xs-6">
<div class="mapNavLeft">Find a Store</div>
</div>
<div class="col-xs-6 mapNavRight">
<a id="mapView">Map View</a> | <a id="listView">List View</a>
</div>
</div>
<div class="row">
<div class="col-xs-12 noPad">
<div id="floating-panel">
<input id="findAddress" name="findAddress" type="textbox" value="Find a Store - City, State, Zip">
<select id="findRadius">
<option value="13" selected="selected">radius</option>
<option value="12">5 miles</option> <!-- 4 miles -->
<option value="11">10 miles</option> <!-- 8 miles -->
<option value="10">15 miles</option> <!-- 16 miles -->
</select>
<input id="findSubmit" type="submit" value="Find a shop" class="btnLeft">
</div>
<div class="sideBar">
<div class="closeBtn">x</div>
<h3>Our Stores:</h3>
</div>
<div id="map"></div>
<div id="outputList"></div>
</div>
</div>
</div><strong>
</strong>

<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&amp;amp;key=**YOUR_KEY_HERE**"</script>;
<script type="text/javascript" src="${sharedResourcePath}/js/locations.js"</script>;
<script type="text/javascript" src="${sharedResourcePath}/js/maps-module.js"</script>;

Locations array example:

var DEALERS = (function() {
var image = '../images/marker.png';

var locations = [
['location name 1',32.215143,-90.151818,map,image,'detailed description'],
['location name 2',47.336401,-116.888100,map,image,'detailed description'],
['location name 3',33.755219,-90.715672,map,image,'detailed description'],
['location name 4',33.646063,-87.058802,map,image,'detailed description'],
['location name 5',48.548468,-117.909399,map,image,'detailed description']
];
})();

 

MAPS MODULE JS:

MAPMOD = (function( window, google, DEALERS ) {

 var gmarkers = [],
 infos = [],
 map = {},
 whichMap = "";

 var init = (function init () {
 
 if( !document.getElementById("map") ) { return; }

 whichMap = $('#map').attr("data-map-type");

 switch( whichMap ) {
 case "dealer":
 var myOptions = {
 //center: new google.maps.LatLng(37.4419, -122.1419),
 zoom: 4,
 mapTypeId: google.maps.MapTypeId.ROADMAP,
 scrollwheel: false,
 disableDefaultUI: true,
 draggable: false,
 scaleControl: false,
 zoomControl: false
 };
 initDealerDetail(myOptions);
 break;

 case "all": 
 var myOptions = {
 zoom: 4,
 mapTypeId: google.maps.MapTypeId.ROADMAP,
 scrollwheel: false
 };
 allDealers(myOptions);
 break;
 }
 });

 var allDealers = (function allDealers (myOptions) {
 
 map = new google.maps.Map( document.getElementById("map"), myOptions );

 setMarkers( map, DEALERS.locations );

 var geocoder = new google.maps.Geocoder();

 var US = {
 NorthEast: {
 lat: 49.38,
 lng: -66.94
 },
 SouthWest: {
 lat: 25.82,
 lng: -124.39
 }
 }
 
 var USbounds = new google.maps.LatLngBounds(new google.maps.LatLng(US.SouthWest.lat, US.SouthWest.lng),
 new google.maps.LatLng(US.NorthEast.lat, US.NorthEast.lng));

 map.fitBounds(USbounds);
 //var USrect = new google.maps.Rectangle({map:map, bounds: USbounds});

 $('#findSubmit').on('click', function() {
 geocodeAddress(geocoder, map);
 });

 $("#findAddress").on("click", function() {
 $(this).val("");
 })

 $("#mapView").on("click", function() {
 $("#outputList").hide();
 $("#map").show();
 })
 
 $("#listView").on("click", function() {
 $("#map").hide();
 $("#outputList").show();
 })
 
 document.onkeydown=function() {
 if(window.event.keyCode=='13') {
 $('#findSubmit').click();
 }
 }

 geolocate(geocoder, map);
 });

 var geolocate = (function geolocate (geocoder, map) {

 // Try HTML5 geolocation.
 if (navigator.geolocation) {

 //var address = document.getElementById('findAddress').value ? document.getElementById('findAddress').value : {};

 navigator.geolocation.getCurrentPosition(function(position) {
 var pos = {
 lat: position.coords.latitude,
 lng: position.coords.longitude
 };

 //infoWindow.setPosition(pos);
 //infoWindow.setContent('Location found.');
 document.getElementById('findAddress').value = pos.lat + " " + pos.lng;
 $('#findRadius').val(8);
 geocodeAddress(geocoder, map);

 //map.setCenter(pos);
 //map.setZoom(9);
 }, function() {
 handleLocationError(true, infoWindow, map.getCenter());
 });
 } else {
 // Browser doesn't support Geolocation
 handleLocationError(false, infoWindow, map.getCenter());
 }
 });

 var initDealerDetail = (function initDealerDetail (myOptions) {

 map = new google.maps.Map( document.getElementById("map"), myOptions );

 setMarkers( map, DEALERS.locations );

 var lat = parseFloat( $('#map').attr("data-map-lat") );
 var lng = parseFloat( $('#map').attr("data-map-lng") );

 var pos = {
 lat: lat,
 lng: lng
 };

 map.setCenter(pos);
 map.setZoom(15);
 map.panBy(-250, 0);
 });
 
 function handleLocationError(browserHasGeolocation, map, pos) {
 map.setPosition(pos);
 map.setContent(browserHasGeolocation ? 'Error: The Geolocation service failed.' : 'Error: Your browser doesn\'t support geolocation.');
 }
 
 function geocodeAddress(geocoder, resultsMap) {
 
 var address = document.getElementById('findAddress').value;
 
 var radius = parseInt($( "#findRadius option:selected" ).val());
 if(isNaN(radius)){ radius = 8; }

 geocoder.geocode({'address': address}, function(results, status) {
 
 if (status === google.maps.GeocoderStatus.OK) {
 resultsMap.setCenter(results[0].geometry.location);

 var marker = new google.maps.Marker({
 map: resultsMap,
 position: results[0].geometry.location,
 });

 closest = findClosestN(results[0].geometry.location,10);

 // get driving distance
 closest = closest.splice(0,10);
 $('#findAddress').val(results[0].formatted_address);

 calculateDistances(results[0].geometry.location, closest,10);
 
 resultsMap.setZoom(radius);
 
 } else {
 $('#findAddress').val("No results. Please try again");
 }
 });
 }
 
 function findClosestN(pt,numberOfResults) {
 var closest = [];

 for (var i=0; i<gmarkers.length;i++) {
 gmarkers[i].distance = google.maps.geometry.spherical.computeDistanceBetween(pt,gmarkers[i].getPosition());
 
 //$('#findAddress').val("process " + i + ":" + gmarkers[i].getPosition().toUrlValue(6) + ":" + gmarkers[i].distance.toFixed(2) + "<br>");
 //gmarkers[i].setMap(null);
 closest.push(gmarkers[i]);
 }
 closest.sort(sortByDist);
 return closest;
 }

 function sortByDist(a,b) {
 return (a.distance- b.distance)
 }

 function calculateDistances(pt,closest,numberOfResults) {
 $('#outputList').html('');
 var service = new google.maps.DistanceMatrixService();
 var request = {
 origins: [pt],
 destinations: [],
 travelMode: google.maps.TravelMode.DRIVING,
 unitSystem: google.maps.UnitSystem.IMPERIAL,
 avoidHighways: false,
 avoidTolls: false
 };
 
 for (var i=0; i<closest.length; i++) request.destinations.push(closest[i].getPosition());
 service.getDistanceMatrix(request, function (response, status) {
 if (status != google.maps.DistanceMatrixStatus.OK) {
 alert('Error was: ' + status);
 } else {
 var origins = response.originAddresses;
 var destinations = response.destinationAddresses;
 
 var results = response.rows[0].elements;
 for (var i = 0; i < numberOfResults; i++) {

 $('#outputList').append('\
 <label for="dealer' + i + '" class="col-xs-8 dealerItem">\
 <input type="radio" value="' + closest[i].title + '" name="dealers" id="dealer' + i + '">\
 <span>' + closest[i].title + '</span>\
 <span class="dealerAddress">' + destinations[i] + '</span>\
 </label>\
 <div class="col-xs-4 distance">' + results[i].distance.text + '</div>');
 }
 }
 });
 }
 
 function setMarkers(map,locations) {
 
 var marker, i
 
 for (i = 0; i < locations.length; i++) { 
 
 var loan = locations[i][0],
 lat = locations[i][1],
 lng = locations[i][2],
 add = locations[i][5];
 
 latlngset = new google.maps.LatLng(lat, lng);

 var marker = new google.maps.Marker({ 
 map: map,
 title: loan ,
 position: latlngset,
 icon: './images/tp.png'
 });

 gmarkers.push(marker);
 
 //console.log(marker.getPosition());
 //map.setCenter(marker.getPosition());
 
 var content = add;
 var infowindow = new google.maps.InfoWindow();
 
 google.maps.event.addListener(marker,'click', (function(marker,content,infowindow){ 
 
 return function() {
 
 /* close the previous info-window */
 closeInfos();
 
 infowindow.setContent(content);
 infowindow.open(map,marker);
 
 /* keep the handle, in order to close it on next click event */
 infos[0]=infowindow;
 
 };

 })(marker,content,infowindow)); 
 
 }
 }
 
 function closeInfos() {
 
 if(infos.length > 0) {
 
 /* detach the info-window from the marker ... undocumented in the API docs */
 infos[0].set("marker", null);
 
 /* and close it */
 infos[0].close();
 
 /* blank the array */
 infos.length = 0;
 }
 }
 
 return {
 init: init
 }

})(window, google, window.DEALERS);
MAPMOD.initMap();

trying out Gulp, node-modules for browerify, babel (to support/convert es6), & bootstrap

Monday, October 5th, 2015

gulpfile.js

var gulp = require('gulp'),
    babel = require('gulp-babel'),
    browserify = require('gulp-browserify'),
    jshint = require('gulp-jshint'),
    less = require('gulp-less'),
    path = require('path'),
    gp_concat = require('gulp-concat'),
    gp_rename = require('gulp-rename'),
    gp_uglify = require('gulp-uglify'),
    gp_sourcemaps = require('gulp-sourcemaps'),
    mainBowerFiles = require('main-bower-files'),
    minifyCSS = require('gulp-minify-css');

// Initial bootstrap setup
// Copy bootstrap from bower-components to public/lib
gulp.task('bower', function() {
    return gulp.src(mainBowerFiles(), {
            base: 'bower_components'
        })
        .pipe(gulp.dest('public/lib'));
});
// overwrite variables.less with our own edited version
gulp.task('bootstrap:prepareLess', ['bower'], function() {
    return gulp.src('public/lib/styles/less/variables.less')
        .pipe(gulp.dest('public/lib/bootstrap/less'));
});
// compile bootstrap less to css
gulp.task('bootstrap:compileLess', ['bootstrap:prepareLess'], function() {
    return gulp.src(['bower_components/bootstrap/less/bootstrap.less'])
    //return gulp.src('public/lib/bootstrap/less/bootstrap.less')
        .pipe(less())
        .pipe(gp_rename('bootstrap.css'))
        .pipe(gulp.dest('public/lib/styles/css'));
});
// End bootstrap setup

// concatenate css files altogether and minify
gulp.task('minifyCSS', function(){
    return gulp.src(['public/lib/styles/css/*.css'])
        .pipe(gp_concat('all.css'))
        .pipe(minifyCSS())
        .pipe(gp_rename('styles.min.css'))
        .pipe(gulp.dest('public/lib/styles/dist'));
});


// Lint/jshint JS
gulp.task('lint', function() {
    return gulp.src('public/lib/js/main.js')
        .pipe(jshint({'esnext': true}))
        .pipe(jshint.reporter('default'));
});


// Concatenate & Minify JS
gulp.task('scripts', function() {
    return gulp.src(['public/lib/js/main.js', 'pubilc/lib/bootstrap/dist/js/bootstrap.js'])
        .pipe(browserify({
            insertGlobals : true,
            debug : false
        }))
        .pipe(babel({compact: false}))
        .pipe(gp_concat('all.js'))
        .pipe(gp_rename('bundle.min.js'))
        .pipe(gp_uglify({ mangle: false }))
        .pipe(gulp.dest('public/lib/js/dist'));
});


// Just convert ES6
var paths = {
    es6: ['es6/myapp.js'],
    es5: 'es5',
    // Must be absolute or relative to source map
    sourceRoot: ('es6'),
};
gulp.task('babel', function () {
    return gulp.src(paths.es6)
        .pipe(gp_sourcemaps.init())
        .pipe(babel({compact: false}))
        .pipe(gp_sourcemaps.write('.', { sourceRoot: paths.sourceRoot }))
        .pipe(gp_rename('bundle.min.js'))
        .pipe(gulp.dest(paths.es5));
});


// start watch CSS & JS files for changes
gulp.task('watch', function() {
    gulp.watch(['public/lib/styles/**/*.*', 'public/lib/js/*.js'], ['lint', 'scripts', 'minifyCSS']);
});


// Default
gulp.task('default', ['lint', 'scripts', 'minifyCSS'], function(){});

Now let’s have a look at main.js using browerify’s require:

/*jshint strict:false */

let loadUnderscore = require('./loadunderscore');
loadUnderscore.logUnderscoreVersion();

let myUtils = require('./myutils');
myUtils.logDate();
myUtils.logMonth();

window.$ = window.jQuery = require('jquery');
require('jquery-ui');

// ES6 experiments, these ARE converted
var getName = () => "Hetal";

$(function(){
	$('#main').text('rewritten 10');
	console.log( $().jquery );
	/*alert('changed!');*/
	
	$( "#draggable" ).draggable();
});

// ES6 experiments, these are not converted/supported
/*
let developer = 'Alex';
console.log('Developer: ${developer}!');

let book = {
	author: 'John',
    title: 'Some Fancy Title'
};

$('#main').append('If you like ${author.name}, then read the new book, ${book.title}');
*/

Reverse Linked List JavaScript

Monday, August 3rd, 2015

Reverse a Linked List in Javascript.
Requires Underscore.js
also here:
http://jsfiddle.net/afrascona/fuhmhqf3/

Array.prototype.getLinkedList = function () {
    var i,
        head;    
    for (i = this.length - 1; i >= 0; i -= 1) {
        head = {
            value: this[i],
            next: head
        };
    }
    return head;
};

function reverseList (head) {
    var current = head,
        tempHead,
        previous;
    while ('object' === typeof current) {
        tempHead = current.next;
        current.next = previous;
        previous = _.clone(current);
        current = _.clone(tempHead);
    }
    return previous;
}

var list = [0,1,2,3,4,5,6,7,8,9].getLinkedList();

console.dir(list);
console.dir(reverseList(list));

MxN Matrix 0 element makes row & column 0s

Monday, August 3rd, 2015
var matrix = [
	[ 2, 3, 1, 4, 5 ],
	[ 4, 6, 0, 9, 8 ],
	[ 3, 2, 1, 8, 2 ],
	[ 6, 3, 4, 7, 6 ],
	[ 8, 5, 7, 2, 1 ]
	],
	saveRows = [],
	saveColumns = [],
	i,
	j;

var onceRowLength = matrix.length;
var onceColumnLength = matrix[0].length;

function displayMatrix(matrix) {
	for ( i = 0; i < onceRowLength; i++ ) {
		for ( j = 0; j < onceColumnLength; j++ ) {
			document.writeln(matrix[i][j]);
		}
		document.writeln('<br />');
	}
}

function saveRowsAndColumns(matrix) {
	for ( i = 0; i < onceRowLength; i++ ) {
		for ( j = 0; j < onceColumnLength; j++ ) {
			if ( matrix[i][j] == 0) {
				saveRows[i] = true;
				saveColumns[j] = true;
			}
		}
	}
}

function zeroTheMatrix(matrix) {
	for ( i = 0; i < onceRowLength; i++) {
		for ( j = 0; j < onceColumnLength; j++ ) {
			if ( saveRows[i] || saveColumns[j] ) {
				matrix[i][j] = 0;
			}
		}
	}
}

displayMatrix(matrix);
saveRowsAndColumns(matrix);
zeroTheMatrix(matrix);
document.writeln('<br />');
displayMatrix(matrix);

Interview Fisher-Yates Shuffle in-place algorithm JavaScript

Wednesday, July 29th, 2015
function shuffle(arrayToShuffle) {
  var arrayLengthCountdown = 	arrayToShuffle.length,
  								lastElementVal,
  								randomIndex;

  while (arrayLengthCountdown) {

    // Pick a random element from the shortening 'length' of the array, the 'front'
    randomIndex = Math.floor(Math.random() * arrayLengthCountdown--);

    console.log('randomIndex: ' + randomIndex + ' arrayLengthCountdown: ' + arrayLengthCountdown + '; swapping ' + arrayToShuffle[randomIndex] + ' with ' + arrayToShuffle[arrayLengthCountdown]);

    // And swap it with the last element of the shortening 'length', taken from the 'back' of the array, which gets injected into the 'front' to await getting shuffled
    lastElementVal = arrayToShuffle[arrayLengthCountdown];
    arrayToShuffle[arrayLengthCountdown] = arrayToShuffle[randomIndex];
    arrayToShuffle[randomIndex] = lastElementVal;

    console.log( arrayToShuffle );
  }

  return arrayToShuffle;
};
shuffle([0,1,2,3,4,5,6,7,8,9]);

Interview JavaScript Module Pattern Singleton

Monday, July 7th, 2014
var accountObj = (function() {
     var balance = 0;
     var type = 'savings';
     return {
          get_balance: function(){
               return balance;
          },
          deposit: function(a){
               balance += a;
          },
     };
}());

var myAccount = accountObj;
document.writeln('Balance: ' + myAccount.get_balance()); // 0
document.writeln('Add 5: ' + myAccount.deposit(5)); // undefined
document.writeln('Balance: ' + myAccount.get_balance()); // 5

Interview JavaScript private methods with closures for multiple objects exercise (not Module Singleton pattern!)

Monday, July 7th, 2014

JavaScript private methods with closures

var accountObj = function() {
     var privateBalance = 0;
     function privateDeposit(val) { privateBalance += val; }
     return {
          deposit: function(n) { privateDeposit(n); },
          balance: function() { return privateBalance; }
     }
};

var myAccount = accountObj();
var yourAccount = accountObj();

myAccount.deposit(10);
console.log('My account balance: ' + myAccount.balance()); //10

yourAccount.deposit(200);
console.log('Your account balance: ' + yourAccount.balance()); //200

myAccount.deposit(5);
console.log('Added 5, balance updated: ' + myAccount.balance()); //15

console.log(myAccount.privateBalance); // undefined

source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

Another example:


var animal = function (spec) {
     var privateName = spec.name;
     var privateSaying = spec.saying;
     var privateReturnName = function(){
          return privateName;
     };
     var privateReturnSaying = function(){
          return privateSaying;
     }
     return {
          get_name: function(){
               return privateReturnName();
          },
          get_saying: function(){
               return privateReturnSaying();
          }
     }
};
var myHorse = animal({name: 'Wilbur', saying: 'Neeeeeeh'});
var myPig = animal({name: 'Charlotte', saying: 'Oink!'});
document.writeln(myHorse.get_name() + ' says ' + myHorse.get_saying()); <span style="color: #ff0000;">// Wilbur says Neeeeeeeh
document.writeln(myPig.get_name() + ' says ' + myPig.get_saying());

document.writeln(myPig.privateSaying); // undefined

JavaScript Factorial with Memoization

Sunday, July 6th, 2014
var memoizer = function (memo, formula) {
     var recur = function(n) {
          var result = memo[n];
          if(typeof result !== 'number') {
               result = formula(recur, n);
               memo[n] = result;
          }
          return result;
     };
     return recur;
};
 
var factorial = memoizer([1,1], function (recur, n) {
     return n * recur(n - 1);
});
 
document.writeln(factorial(10)); // 3628800

credit: Crockford, Douglas. JavaScript: The Good Parts, p.45. O’Reilly 2008

JavaScript Fibonacci with & without Memoization

Sunday, July 6th, 2014

// simple Fibonacci w/o Memoization

var fibonacci = function(n){
     return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};
var showF = function(n){
     for(var i = 0; i <= n; i += 1) {
          document.writeln('//' + i + ': ' + fibonacci(i));
     }
};

showF(10); //55

 

//Fibonacci with Memoization

var fibonacci = (function() {
     var memo = {};

     function f(n) {
          var value;
          if (n in memo) {
               value = memo[n];
          } else {
               if (n === 0 || n === 1)
               value = n;
          } else {
               value = f(n - 1) + f(n - 2);
               memo[n] = value;
          }
          return value;
     }
     return f;
})();

document.writeln(fibonacci(50));

 

// Fibonacci with Memoizer abstracted function

var memoizer = function (memo, formula) {
     var recur = function(n) {
          var result = memo[n];
          if(typeof result !== 'number') {
               result = formula(recur, n);
               memo[n] = result;
          }
     return result;
     };
     return recur;
};

var fibonacci2 = memoizer([0,1], function (recur, n) {
     return recur(n - 1) + recur(n - 2);
});

document.writeln(fibonacci2(50)); <span style="color: #ff0000;">//12586269025</span>

 

credit: Crockford, Douglas. JavaScript: The Good Parts, p.45. O’Reilly 2008

credit: http://www.sitepoint.com/implementing-memoization-in-javascript/

JavaScript Curry

Sunday, July 6th, 2014

// Curry

“Currying allows us to produce a new function by combining a function and an argument”

Function.prototype.method = function (name, func) { // makes Augmenting Types beautifully easy when needed
if (!this.prototype[name]) {
this.prototype[name] = func;
return this;
}
};

var add = function (a, b) {
return a + b;
};

Function.method(‘curry’, function () { // leveraging our Augmentation shortcut…
var slice = Array.prototype.slice,
args = slice.apply(arguments),
that = this;

return function () {
return that.apply(null, args.concat(slice.apply(arguments)));
};
});

var add1 = add.curry(1);
document.writeln(add1(6)); //7

 

credit:

Crockford, Douglas. JavaScript: The Good Parts, p.43. O’Reilly 2008

Foundation 5 Framework Animate Accordion (multiple, with dynamic AJAX content using reflow, and also nested)

Monday, January 27th, 2014

Out of the box there is no animation on these.  I tried for a CSS3 transition but couldn’t get one. If anyone finds one do tell. Anyhow, my current project has 3 accordion levels, the main off-canvas accordion, a second one loaded dynamically via AJAX into the main content area, and third level of accordions nested in each of the 2nd level accordions.

First, I gave them each an id, so that I could address them easily and individually:

<dl class=”accordion firstLevelAccordions” data-accordion> (in the ‘off-canvas’ left)

<dl class=’accordion secondLevelAccordions’ data-accordion> (in the main content right section, content thereof loaded dynamically via AJAX)

<dl class=’accordion thirdLevelAccordions’ data-accordion> (this one nested inside the secondLevelAccordions)

After the dynamic content load, Foundation makes you reflow to find/activate the new content:

$(document).foundation(‘reflow’);

The initialization of each accordion (you could merge these into one function, or parameter-ize the class piece, but for simplicity’s sake, this works just fine):

$(function(){ // onready

// first level off-canvas menu accordions
$(document).on(“click”, “.firstLevelAccordions > dd:not(‘.active’) > a”, function (event) {
$(“.firstLevelAccordions > dd.active”).removeClass(‘active’).children(“.content”).slideUp(1000);
$(this).parent().addClass(‘active’).children(“.content”).slideToggle(1000);
})

$(document).on(“click”, “.firstLevelAccordions > dd.active > a”, function (event) {
$(“.firstLevelAccordions > dd.active”).removeClass(‘active’).children(“.content”).slideUp(1000);
$(this).parent().removeClass(‘active’);//.find(“.content”).slideToggle(“fast”);
})

// second level article list/detail accordions
$(document).on(“click”, “.secondLevelAccordions > dd:not(‘.active’) > a”, function (event) {
$(“.secondLevelAccordions > dd.active”).removeClass(‘active’).children(“.content”).slideUp(1000);
$(this).parent().addClass(‘active’).children(“.content”).slideToggle(1000);
})

$(document).on(“click”, “.secondLevelAccordions > dd.active > a”, function (event) {
$(“.secondLevelAccordions > dd.active”).removeClass(‘active’).children(“.content”).slideUp(1000);
$(this).parent().removeClass(‘active’);//.find(“.content”).slideToggle(“fast”);
})

// third level nested accordions
$(document).on(“click”, “.thirdLevelAccordions > dd:not(‘.active’) > a”, function (event) {
$(“.thirdLevelAccordions > dd.active”).removeClass(‘active’).children(“.content”).slideUp(1000);
$(this).parent().addClass(‘active’).children(“.content”).slideToggle(1000);
})

$(document).on(“click”, “.thirdLevelAccordions > dd.active > a”, function (event) {
$(“.thirdLevelAccordions > dd.active”).removeClass(‘active’).children(“.content”).slideUp(1000);
$(this).parent().removeClass(‘active’);//.find(“.content”).slideToggle(“fast”);
})

});

Angularjs switching ngview view-container animation direction – left, then right – using view-frames and keyframes and rootScope

Sunday, January 26th, 2014

index.html:

<div class=”view-container” id=”view-containerWrapper”>
<div class=”{{rootAnimation}}” ng-view></div>
</div>

_animate.scss:

.view-container {
/* position: relative;*/
}
/* Index loads w/o animation */
.view-frame-0.ng-enter {
background: white;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.view-frame-0.ng-leave {
background: white;
position: absolute;
top: 0;
left: 0;
right: 0;
}
/* Page 2 animated in from the right, index animates out to the left */
.view-frame-1.ng-enter {
background: white;
position: absolute;
top: 0;
left: 0;
right: 0;

-webkit-animation: 1.0s slide2;
-moz-animation: 1.0s slide2;
-o-animation: 1.0s slide2;
animation: 1.0s slide2;
z-index: 100;
}

.view-frame-1.ng-leave {
background: white;
position: absolute;
top: 0;
left: 0;
right: 0;
width:100%;

-webkit-animation: 1.0s slide0;
-moz-animation: 1.0s slide0;
-o-animation: 1.0s slide0;
animation: 1.0s slide0;
z-index: 100;
}
/* Page 2 animates out to the right, index animates back from the left */
.view-frame-2.ng-enter {
background: white;
position: absolute;
top: 0;
left: 0;
right: 0;
width:100%;

-webkit-animation: 1.0s slide3;
-moz-animation: 1.0s slide3;
-o-animation: 1.0s slide3;
animation: 1.0s slide3;
z-index: 100;
}

.view-frame-2.ng-leave {
background: white;
position: absolute;
top: 0;
left: 0;
right: 0;

-webkit-animation: 1.0s slide1;
-moz-animation: 1.0s slide1;
-o-animation: 1.0s slide1;
animation: 1.0s slide1;
z-index: 100;
}

/* Slide 0 – From active to the left */
@keyframes slide0 {
0% {
left: 0;
top: 0;
}
100% {
left: -100%;
top: 0;
}
}
@-moz-keyframes slide0 {
0% {
left: 0;
top: 0;
}
100% {
left: -100%;
top: 0;
}
}

@-webkit-keyframes slide0 {
0% {
left: 0;
top: 0;
}
100% {
left: -100%;
top: 0;
}
}

@keyframes slide0 {
0% {
left: 0;
top: 0;
}
100% {
left: -100%;
top: 0;
}
}

@-moz-keyframes slide0 {
0% {
left: 0;
top: 0;
}
100% {
left: -100%;
top: 0;
}
}

@-webkit-keyframes slide0 {
0% {
left: 0;
top: 0;
}
100% {
left: -100%;
top: 0;
}
}

/* slide 1 – from active to the right */

@keyframes slide1 {
0% {
left: 0;
top: 0;
}
100% {
left: 100%;
top: 0;
}
}
@-moz-keyframes slide1 {
0% {
left: 0;
top: 0;
}
100% {
left: 100%;
top: 0;
}
}

@-webkit-keyframes slide1 {
0% {
left: 0;
top: 0;
}
100% {
left: 100%;
top: 0;
}
}

@keyframes slide1 {
0% {
left: 0;
top: 0;
}
100% {
left: 100%;
top: 0;
}
}

@-moz-keyframes slide1 {
0% {
left: 0;
top: 0;
}
100% {
left: 100%;
top: 0;
}
}

@-webkit-keyframes slide1 {
0% {
left: 0;
top: 0;
}
100% {
left: 100%;
top: 0;
}
}

/* slide 2 – from the right to active */

@keyframes slide2 {
0% {
left: 100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}
@-moz-keyframes slide2 {
0% {
left: 100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

@-webkit-keyframes slide2 {
0% {
left: 100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

@keyframes slide2 {
0% {
left: 100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

@-moz-keyframes slide2 {
0% {
left: 100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

@-webkit-keyframes slide2 {
0% {
left: 100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

/* slide 3 – from the left to active */

@keyframes slide3 {
0% {
left: -100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}
@-moz-keyframes slide3 {
0% {
left: -100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

@-webkit-keyframes slide3 {
0% {
left: -100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

@keyframes slide3 {
0% {
left: -100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

@-moz-keyframes slide3 {
0% {
left: -100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

@-webkit-keyframes slide3 {
0% {
left: -100%;
top: 0;
}
100% {
left: 0;
top: 0;
}
}

products.html:

<div ng-repeat-start=”prod in products” headersloaded class=”followMeBar”>
<i class=”iseFontIcons icon-{{prod.icon}}”></i>
{{ prod.Name | uppercase }}
</div>

<ul class=”nav nav-tabs nav-stacked” ng-repeat-end>
<li ng-repeat=”cat in prod.Categories” productsloaded>
<a href=” ng-click=’go(“product_{{prod.ID}}/category_{{cat.ID}}”,”view-frame-1″)’>{{cat.Name}}</a>
</li>
</ul>

finally, in the controller…that go method:

$scope.go = function(path,newAnimation) {
$rootScope.rootAnimation = newAnimation;
$location.path(path);
}

 can’t remember if this ends up mattering, if so just for the sake of it, the important wrappers from _main.scss:

#mainWrap{
position:relative;
}
.ng-view{
position:relative;
}
#headerBar{

width:100%;
}
.view-container{
width:100%;
position: relative;
}
#view-containerWrapper{
position:relative;
}
.viewsWrapper{
border-right: 1px solid #f1f1f1;
border-left: 1px solid #f1f1f1;
width:100%;
position:absolute;
}
#productsWrapper{
top:0px;
z-index:0;
}

simple JavaScript allow only digits/numbers in input field

Wednesday, October 23rd, 2013

<input onkeypress=”validate(event)” />

function validate(evt) {
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode( key );
var regex = /[0-9]/;
if( !regex.test(key) ) {
theEvent.returnValue = false;
if(theEvent.preventDefault) theEvent.preventDefault();
}
}

jQuery Regex Selector examples ^=Starts with, $=Ends with, is of Class [0-9] threw in an encodeURIComponent for kicks

Monday, August 12th, 2013

Obviously, if your jQuery version is up to date, you should use .on
but I was fixing one of our sites that is stuck in 1.5,
so here are some examples using .delegate and .bind
The regex blocks are the same either way:

$.fn.popSubject = function() {
var menuA = $(“#askMenuA option:selected”).text();
var menuB = $(“#askMenuB option:selected”).text();
$(‘input[id$=”hiddensubject”]‘).val(menuA + ” – ” + menuB);
}

$(‘[id^=rn_FormSubmit_][id$=_Button]‘).bind(‘click’, ‘button’, function(event){
//Call Omniture when SA initial form submitted
s_exp_trackClick( this, ‘a’,”support.faq.sa.first.” + encodeURIComponent($(“#askMenuA option:selected”).text()) );
});

$(“body”).delegate(‘[id^=rnDialog1_Button][id$=[0-9]]‘, ‘click’, function(event){
//Call Omniture when SA dialog box submitted
s_exp_trackClick( this, ‘a’,’support.faq.sa.pop.’+ encodeURIComponent($(“#askMenuB option:selected”).text()) );
});

reverse a String

Wednesday, August 7th, 2013

JAVA

class Reverso{
	public static void main(String[] args) {
		for (String toReverse: args) {
			int countOf = toReverse.length();
			for(int $i = toReverse.length() - 1; $i >= 0; $i--){
				System.out.print(toReverse.charAt($i));
			}
		}
	}
}

JavaScript

var reverse = function(str) {
    var arr = [];

    for (var i = 0, len = str.length; i <= len; i++) {
        arr.push(str.charAt(len - i))
    }

    return arr.join('');
}

document.writeln(reverse('lorem ipsum dolor'));

Simple Linked List example JavaSript

Wednesday, July 31st, 2013
// items of the list
var bird = {name:'Mockingbird'};
var cat = {name:'Keyboard'};
var dog = {name:'Fort'};
var duck = {name:'Scrooge'};

// the linked-list itself
var animals = {
    head : bird
};

// each item of the list stores a reference to the next one
bird.next = cat;
cat.next = dog;
dog.next = duck;

// output
var animal = animals.head;
while (animal) {
    console.log(animal.name);
    animal = animal.next;
}

source: http://blog.millermedeiros.com/linked-lists/

load external JavaScript from within another JS

Monday, February 25th, 2013

Of course there are many ways to do this, js loading libraries/managers,
what if you can’t get to the html though, and want to have control over all JS functions externally,
say from the JS files alone on a separate CDN… a JS ‘include’ is what we need…
since jQuery 1.8, in order to get a callback to take action in the even that the file doesn’t load,  a ton of different solutions that used to work, no longer do, and with jsonp or script type calls, the error function doesn’t even get called, here’s to trying to get one to work:

complete, success, .error, and on and on…

but no, solution:

var jqxhr = $.ajax({
url: “http:/…”,
dataType: ‘script’,
crossDomain: true,
timeout: 5000,
cache: false
})
//.done(function() { alert(“success”); })
.fail(function() { ajaxFailure(); })
//.always(function() { alert(“complete”); });

 

reference: http://api.jquery.com/jQuery.ajax/

JavaScript Backbone Hash App #4 – activate it

Monday, January 7th, 2013

$(function(){ // onready
// App initiations
var appRouter = new AppRouter(); // Router initialization 
Backbone.history.start(); // Backbone start
});

// I like to use an initial loader script to load the app in the order desired, or you could use LABS or similar, in this case something like:

– /lib/jQuery, /lib/underscore, /lib/backbone,
– then our app files: /app/router, /app/models, /app/views
– finally, this file

JavaScript Backbone Hash App #3 – the view

Monday, January 7th, 2013

// Search
var SearchButtonView = Backbone.View.extend({
el: ‘.goBtnOutside’,
template: _.template(‘<input type=”submit” id=”searchButton” class=”goButton” alt=”Search” title=”Go” value=”Go”>’),
initialize: function(){
},
render: function() {
return this;
},
events: {
‘click #searchButton’: ‘fireSearch’
},
fireSearch: function(e) {
var searchRequest = $(‘#some-field’).val();
if(searchRequest == ”){
Backbone.history.navigate(“AllAnswers”, true);
}
else{
Backbone.history.navigate(“Search:” + searchRequest, true);
}
}
});
var MakeSearchButton = new SearchButtonView();

JavaScript Backbone Hash App #2 – the model – jsonp

Monday, January 7th, 2013

//Answer Model
var AnswerModel = Backbone.Model.extend({

initialize: function(attributes, options) {
//passed in
this.Callback = attributes.callback;
this.Method = attributes.methodNeeded;
this.answerId = attributes.answerId;
},
url: function() {
return ‘http://’ + controllerUrl + ‘/cc/kfController/’ + this.Method + ‘/’ + this.answerId;
},

// override backbone synch to force a jsonp call
sync: function(method, model, options) {
var params = _.extend({
type: ‘GET’,
dataType: ‘jsonp’,
jsonpCallback: this.Callback,
url: model.url()+”?callback=?”,
processData: false
}, options);

// Make the request.
return $.ajax(params);
}
});

JavaScript Backbone Hash App #1 – the router

Monday, January 7th, 2013

// this helps the app remain configurable, moveable, thus this ‘state’ of the app is extracted
var mostPopularAnswersHashText = “MostPopular”

//Router
var AppRouter = Backbone.Router.extend({

routes: {
”: ‘home’,
‘index.php’: ‘home’,
‘Search::searchQuery’ : ‘search’, // Matches http://support.htm/#Search:query
‘Search/:searchQuery’ : ‘search’, // Matches http://support.htm/#Search/query
‘:globalState’ : ‘globalStates’, // Matches http://example.com/#six
‘a_id/:answerIdInput’: ‘answerDetails’, // Matches http://example.com/#a_id/34
‘*actions’: ‘defaultAction’ // Matches http://example.com/#anything-here
},

defaultAction : function(){
this.navigate(mostPopularAnswersHashText, {trigger: true});
},
home : function(){
takeDown();
tracer(‘index’);
appProcessing = false;
this.navigate(mostPopularAnswersHashText, {trigger: true});
},

search : function(searchQuery){
searchResults = ‘Search/’ + searchQuery;

var portal = new AnswerModel({
//passing these values to the Model, which simply hits an AJAX server service
methodNeeded: ‘searchAjax’, answerId: prodID + ‘/’ + searchQuery, callback: ‘searchResults’
});
portal.fetch({
success: function(response,xhr) {
// Pass returned populated model to a View & render
var output = new AllAnswersView({ model : ‘AnswerModel’ });
output.render(response);
},
error: function (errorResponse) {
}
});
},

globalStates : function(globalState){

switch(globalState){

case mostPopularAnswersHashText:
var portal = new AnswerModel({
methodNeeded: ‘displayAnswersAjax’, answerId: prodID, callback: ‘callResponse’
});
portal.fetch({
success: function(response,xhr) {
var output = new MostPopularView({ model : ‘AnswerModel’ });
output.render(response);
},
error: function (errorResponse) {
}
});
break;

case allAnswersHashText:
case allTravelToolsHashText:
case allTravelEssentialsHashText:
case allTravelAdvisoriesHashText:

if(globalState == allAnswersHashText){ searchQuery = ”; }
if(globalState == allTravelToolsHashText){ searchQuery = ‘/c_travel-tools’; }
if(globalState == allTravelEssentialsHashText){ searchQuery = ‘/c_travel-essentials’; }
if(globalState == allTravelAdvisoriesHashText){ searchQuery = ‘/c_travel-advisories’; }

var portal = new AnswerModel({methodNeeded: ‘searchAjax’, answerId: prodID + ‘/’ + searchQuery, callback: ‘searchResults’});
portal.fetch({
success: function(response,xhr) {
var output = new AllAnswersView({ model : ‘AnswerModel’ });
output.render(response);
},
error: function (errorResponse) {
}
});
break;
}
},

answerDetails : function(answerIdInput){
// Initiate an Answer Model, pass it the desired ID
var portal = new AnswerModel({methodNeeded: ‘getFullAnswersAjax’, answerId: answerIdInput, callback: ‘answerContentResponse’});
portal.fetch({
success: function(response,xhr) {
// Pass returned populated model to a View, render
var article = new AnswerIdView({ model : ‘AnswerModel’ });
article.render(response);
},
error: function (errorResponse) {
tracer(errorResponse);
}
});
}
});

Simple Javascript var_dump equivalent object interate print

Friday, December 7th, 2012

var out = ”;
for (var i in params) {
out += i + “: ” + params[i] + “\n”;
}
console.log(out);

Javascript call parent window’s functions from child popup window

Tuesday, October 16th, 2012

It’s that simple:

Parent:

<script >function something(){ alert(‘here’); }</script >

Popup:

<script> window.opener.something(); </script >

http://www.w3schools.com/jsref/prop_win_opener.asp

jQuery .hover change div background-position example

Wednesday, November 16th, 2011

example for reference:

$(“#formButtonSubmit“).hover(function(){
$(this).css({
backgroundPosition: ‘0px 0px’
});
}, function(){
$(this).css({
backgroundPosition: ‘0px 30px’
});
});

Secure HTML form example using PHP htmlentities, passing a token PHP, AJAX submission via jQuery

Wednesday, September 21st, 2011

<? php
// form page (index.php): initialize a session so that we can set a unique, random, encrypted value to a user session
session_start();
$token = md5(uniqid(rand(), true));
$_SESSION[‘token’] = $token;
? >
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<script src=”js/jquery.js” type=”text/javascript”></script>
<script src=”js/jquery.validation.js” type=”text/javascript”></script>
<script src=”js/registerSubmit.js” type=”text/javascript”></script>
</head>
<body>
<!– The Form –>
<form id=”topForm” name=”topForm” method=”post”>
<input type=”hidden” name=”token” id=”token” value=”<? php echo $token; ? >” />
<input name=”emailAddress” id=”emailAddress” value=”Email address” onclick=”if( this.value == ‘Email address’ ){ $(this).val(”); }” onblur=”if( this.value == ”){ $(this).val(‘Email address’); }” />
</form>
</body>
</html>

// The jquery.validation.js class uses a regular expression to stop the process if the email entered isn’t acceptable

;(function($) {
$.validation = {};
$.extend( $.validation, {
email:function(email) {
var filter = /^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/;
if ( filter.test(email) ) {
return true;
}
return false;
}
});
})(jQuery);

// The registerSubmit.js submits the entered email via AJAX, returning a success or failure message, to our contactSubmit.php script, which handles the submission of the new email to a database

$(document).ready(function() {

$(“#reg-button”).click(function(){
$(“#topForm”).submit();
});

$(“#topForm”).submit(function(event) {
event.preventDefault();
var $form = $( this ),
emailAddress = $form.find( ‘input[name=”emailAddress”]’ ).val(),
token = $form.find( ‘input[name=”token”]’ ).val(),
formaction = $form.attr( ‘action’ );

if($.validation.email(emailAddress)){
$( “#reg-description” ).html (“submitting…”);
$.ajax({
type: “POST”,
url: “contactSubmit.php”,
data: “firstName=” + firstName + “&lastName=” + lastName + “&emailAddress=” + emailAddress + “&token=” + token,
success: function(){
$( “#reg-description” ).html( “Thank you. You have been registered.” );
},
});
}
else{
$( “#emailAddress” ).val (“Please enter a valid email address”);
}
});
});

// contactSubmit.php:  receive the email, check the token, clean the data, pass to a database layer API

<? php
session_start();

set_include_path(‘DBlayerClass’);
require_once(‘EmailContact.php’);

if (isset($_SESSION[‘token’]) && $_POST[‘token’] == $_SESSION[‘token’]){
if(isset($_POST[’emailAddress’])){
$emailAddress = htmlentities($_POST[’emailAddress’]);
} else { $emailAddress = ”; }

$contact = new EmailContact($emailAddress)

try {
$contact->save();
} catch (Exception $e) {
; // do something
}
//$retrieve = new EmailContact($emailAddress);
//$retrieve->load();
//print_r($retrieve);
//}
? >

Post via jQuery across domains (in this case to a Zend Controller and subsequent view) and display the results

Thursday, August 25th, 2011

the jQuery posting page, in brief:

<document…>
<head>
<script src=”http://code.jquery.com/jquery-1.5.js”></script>
</head>
<body>
<form id=”enewsform” name=”enewsform” action=”http://componentserver/controllername/post” method=”post”>
<input type=”text” name=”email” id=”email” value=”<?php echo $_REQUEST[’email’]; ?>” />
<a id=”submitsubscribe” title=”Subscribe” href=”javascript:{}” onclick=”return false;”>sign up</a>
</form>
<script src=”http://components.someserver.com/js/jquery.validation.js” type=”text/javascript”></script>
<script>
$(‘#submitsubscribe’).click(function(){
$(“#enewsform”).submit();
});

$(“#enewsform”).submit(function(event) {
event.preventDefault();
$( “#result” ).html (“submitting…”);
var $form = $( this ),
term = $form.find( ‘input[name=”email”]’ ).val(),
url = $form.attr( ‘action’ );

if($.validation.email(term)){
$.getJSON(url + “?email=” + term + “&jsoncallback=?”, function(data){
$( “#result” ).html( data[‘error’] );
if(data[‘error’]== “errormatchingstring”){
$( “#result” ).html( “Seems like it worked” );
}else{ $( “#result” ).html(data[‘error’]); }
});
}
else{ $( “#result” ).html (“Please enter your email address”); }

});
</script>

<div id=”result”></div>

// the component Zend controller in question receives the post, does whatever it does, renders its view, and we access the results from the view (don’t forget to pass data to the view with something like this:
$this-> view-> viewresult = $this-> viewData;)

<? php
echo $_REQUEST[‘jsoncallback’] . ‘(‘ . json_encode($this-> viewresult) . ‘)’;
? >

Persistence of GET URL parameters passed to WordPress site with Permalink clean pretty URLs turned on

Friday, April 15th, 2011

Here’s the scenario:
We have a store site.
The store site has a link on its homepage that leads to a wordpress site.
When a visitor clicks the link,
we want a url parameter that is passed with the visitor to the wordpress site
to remain in the url
so that when/if they click a link in the wordpress site that leads back to the store,
the parameter comes back with them.

Normally, you’d simply add a $_GET in your theme somewhere,
assign it to a variable,
and then append that onto any links that are headed back to the store site.

The trouble, though, is that when WordPress’
clean and pretty Permalinks URL function is active,
it takes over, and forwards (via htaccess, wordpress base code functions, or otherwise),
at which point in time data passed over is lost.

Solution:
In WordPress’ index.php (the very first root directory index),
include another file.

include(‘passback.php’);

In that file, instantiate SERVER SESSIONS, and save received parameters.
Something like this (of course looping through the REQUEST parameters dynamically would be smarter, but for simplicities sake, let’s just target a particular parameter):

session_start();
if($_GET[‘persistme’] != ”){ $passit = $_GET[‘persistme’]; }
if(!isset($_SESSION[‘passback’])){ $_SESSION[‘passback’] = $passit; }

Now you can include your passback retrieval class in your theme, grab the parameter, and use your JavaScript library of choice to loop through all the links in the page and append it onto them.
Something like this (Prototype, and only appending links that already have a ? and thus other parameters they’re sending back…):

document.observe(‘dom:loaded’, function() {
$$(“a”).each(function(a) {
newhref = a.href;
if(newhref.include(‘?’){
newhref = a.href + “?rememberme=<?php echo $passit; ?>”;
a.writeAttribute(‘href’, newhref);
}
});
});

jQuery json crossdomain example

Tuesday, March 22nd, 2011

<script src=”http://code.jquery.com/jquery-1.5.js”></script>

<script>

$(“#enews_signup_form”).submit(function(event) {

// stop form from submitting normally
event.preventDefault();

$( “#result” ).html (“submitting…”);

var $form = $( this ),
term = $form.find( ‘input[name=”enews_email”]’ ).val(),
url = $form.attr( ‘action’ );

$.getJSON(url + “?email=” + term + “&jsoncallback=?”, function(data){
$( “#result” ).html( data[‘error’] );
});

});

</script>

<? php

echo $_REQUEST[‘jsoncallback’] . ‘(‘ . json_encode($this-> viewresult) . ‘)’;

?>

WordPress limit search form to a category

Thursday, December 9th, 2010

example:

 

<script>
function submitter()
{
track_it(‘/podcast/searchFormSubmit/’);
document.searchform.submit();
}

</script>

 

<form method=”get” name=”searchform” id=”searchform” action=”<?php bloginfo(‘url’); ?>/”>

 

<input type=”text” value=”<?php the_search_query(); ?>” name=”s” id=”s” onclick=”this.value=””/>

 

This is the important new line, 5 is an example category id

 

<input type=”hidden” name=”cat” value=”5″ />

 

<a href=”javascript:submitter()” style=”text-decoration:none;font-size:11px;margin:0 0 0 5px;position:absolute;top:0px;”><img src=”wp-content/themes/New/images/go.png” onmouseover=”this.src=’wp-content/themes/New/images/go-over.png'” onmouseout=”this.src=’wp-content/themes/New/images/go.png'” border=”0″ />

 

</a>
</form>

 

source: http://wpgarage.com/code-snippets/how-to-hack-the-wordpress-search-function-search-categories-and-child-categories/

 

jQuery check if image with specific source exists on page

Thursday, November 18th, 2010

$(document).ready(function() {

$(“img”).each(function(){
imgtofind = “http://alexyz.com/images/example.jpg”;
source = $(this).attr(‘src’);
if(source == imgtofind){
alert(source); // or otherwise
}
});

}

jQuery select anchor tags that contain specific text, then change id, onClick (Capitalized!!!!), href, :contains, .attr(), .each()

Wednesday, November 17th, 2010

Easy actually, on load, select an anchor tag (or several, and do the following for .each()), that contains, among other contents, the word ‘Read’,

then set its id attribute, a Mouse event, and alter its href value:

$(document).ready(function(){

$(“a:contains(‘Read’)”).each(function(){

$(this).attr(‘id‘,’newid’);

$(this).attr(‘onClick‘, ‘return false;’); // Capitalize the C!!!!

$(this).attr(‘href‘, ‘http://www.alexyz.com’);

});

});

// alternatively, line them all up like this:

$(this).attr(‘id‘,’newid’).attr(‘onClick‘,’return false;’).attr(‘href‘,’http://www.alexyz.com’);

 

// UPDATE: Better method

$(“a[href*=‘search phrase’]”).each(function(){
var postId = $(this).attr(“href”).split(‘?’)[1].split(‘=’)[1].split(‘#’)[0]; // of course this will vary by need
$(this).attr(“href“,”?version=full&source=folder&post=”+postId);
});

Support Prototype script.aculo.us and jQuery, page built with Prototype now being pulled into page that uses jQuery

Tuesday, November 2nd, 2010

So I developed a handful of sites several years ago using Prototype and script.aculo.us,

but now they’re being pulled into/included/required by pages, a site, that is strictly jQuery,

so I need to amend the Prototype site’s functions to check which library is loaded and then act accordingly.

It begs the question, if I were doing this completely fresh, which pattern (see Design Pattern posts) would I attempt to employ…? For example, I’d love to have the option right now to simply write an adapter pattern function instead of burying this conditional within each function…

Aside from Namespacing either or both libraries of course…

Example:

<script>
accordianing = false;
function comments_cabinet()
{
if(accordianing == true)
{
setTimeout( function() { accordian(); }, 25);
}
else
{
accordianing = true;
/* scriptaculous */
if(window.Prototype)
{

if($(‘comments_button’).style.display == ‘none’) // notice the Prototype standard $(”)
{
new Effect.BlindDown(‘comments_button’, {
duration: 0.5,
afterFinish: function(){
accordianing = false;
}
});
}
else
{
new Effect.BlindUp(‘comments_button’, {
duration: 0.5,
afterFinish: function(){
accordianing = false;
}
});
}
}
else
{

$(‘#comments_button’).toggle(‘slow’); // otherwise, use the jQuery version $(‘#’)
accordianing = false;
}
return false;
}
}
</script>

memory jogger: Chain of responsibility, Polymorphism, Design Pattern reference, Decorator pattern, Singleton

Saturday, August 21st, 2010

Good stuff, take a moment to refresh and review:

Chain of responsibility:
http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern
Polymorphism:
http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming
JavaScript really OOP?:
http://articles.techrepublic.com.com/5100-10878_11-1044656.html
http://mckoss.com/jscript/object.htm
JS Prototype object:
http://www.javascriptkit.com/javatutors/proto4.shtml
Design Patterns reference/list:
http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29
Decorator Pattern:
http://en.wikipedia.org/wiki/Decorator_pattern
Loose Coupling def:
http://en.wikipedia.org/wiki/Loose_coupling
Singleton Pattern:
http://en.wikipedia.org/wiki/Singleton_pattern

I always like to have a nice simple AJAX example on hand, you never know…

Tuesday, July 27th, 2010

reference:

http://w3schools.com/php/php_ajax_php.asp

HTML:

<html>
<head>
<script type=”text/javascript”>
function showHint(str)
{
if (str.length==0)
{
document.getElementById(“txtHint”).innerHTML=””;
return;
}
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject(“Microsoft.XMLHTTP”);
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById(“txtHint”).innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open(“GET”,”gethint.php?q=”+str,true);
xmlhttp.send();
}
</script>
</head
<body>

<p><b>Start typing a name in the input field below:</b></p>
<form>
First name: <input type=”text” onkeyup=”showHint(this.value)” size=”20″ />
</form>
<p>Suggestions: <span id=”txtHint”></span></p>

</body>
</html>

Script:

<?php
// Fill up array with names
$a[]=”Anna”;
$a[]=”Brittany”;
$a[]=”Cinderella”;
$a[]=”Diana”;
$a[]=”Eva”;
$a[]=”Fiona”;
$a[]=”Gunda”;
$a[]=”Hege”;
$a[]=”Inga”;
$a[]=”Johanna”;
$a[]=”Kitty”;
$a[]=”Linda”;
$a[]=”Nina”;
$a[]=”Ophelia”;
$a[]=”Petunia”;
$a[]=”Amanda”;
$a[]=”Raquel”;
$a[]=”Cindy”;
$a[]=”Doris”;
$a[]=”Eve”;
$a[]=”Evita”;
$a[]=”Sunniva”;
$a[]=”Tove”;
$a[]=”Unni”;
$a[]=”Violet”;
$a[]=”Liza”;
$a[]=”Elizabeth”;
$a[]=”Ellen”;
$a[]=”Wenche”;
$a[]=”Vicky”;

//get the q parameter from URL
$q=$_GET[“q”];

//lookup all hints from array if length of q>0
if (strlen($q) > 0)
{
$hint=””;
for($i=0; $i<count($a); $i++)
{
if (strtolower($q)==strtolower(substr($a[$i],0,strlen($q))))
{
if ($hint==””)
{
$hint=$a[$i];
}
else
{
$hint=$hint.” , “.$a[$i];
}
}
}
}

// Set output to “no suggestion” if no hint were found
// or to the correct values
if ($hint == “”)
{
$response=”no suggestion”;
}
else
{
$response=$hint;
}

//output the response
echo $response;
?>

Close Fancybox from within, old (1.2) and new (1.3)

Thursday, July 1st, 2010

In 1.2 this worked:

onclick=”$(“#fancy_outer”,window.parent.document).hide(); $(“#fancy_overlay”,window.parent.document).hide();

1.3+ this has changed to:

onclick=”parent.$.fancybox.close();

jQuery replace all img tags with certain source…

Monday, June 7th, 2010

$(‘img’).each(function(){
var t=$(this);
var src1 = t.attr(‘src’);
var newSrc = “images/play2.png”;
if(src1 == “images/play.png”)
{
$(this).attr(‘src’, newSrc);
}
});

JavaScript URL parse to load multiple versions

Monday, June 7th, 2010

<script type=”text/javascript” src=”js/jquery-1.3.2.min.js”></script>

<script>
$(document).ready(function() {

<!– Version requested START –>
if (location.search != “”)
{
x = location.search.substr(1).split(“;”)
for (var i=0; i<x.length; i++)
{
y = x[i].split(“=”);
//alert(y[0] + ” ” + y[1])

// Version 2 (/?version=2)
if( y[1] == 2 ){
// do things
}

// Version 3 (/?version=3)
if( y[1] == 3 ){
// do things
}
}
}
<!– Version requested END –>

jQuery .css background-image / .attr src examples

Monday, June 7th, 2010

$(“body”).css(“background-image”, “url(images/bg2.jpg)”);
$(“#header”).css(“background-image”, “url(images/bg-header2.png)”);
$(“#browse”).css(“background-image”, “url(images/bg-browse2.png)”);
$(“#paginate-slider2”).css(“background-image”, “url(images/bg-slide-thumbs2.jpg)”);
$(“#slides”).css(“background-image”, “url(images/bg-slides2.png)”);
$(“#ST-now”).css(“background-image”, “url(images/bg-STnow2.png)”);
$(“#searchBox”).attr(“src”, “images/search-box2.jpg”);
$(“#keywordsBox”).attr(“src”, “images/keywords2.jpg”);
$(“#inBox”).attr(“src”, “images/products2.jpg”);

jQuery add stylesheet dynamically

Monday, June 7th, 2010

within some logic, a function, elsewhere :

var link = $(“<link>”);
link.attr({
type: ‘text/css’,
rel: ‘stylesheet’,
href: ‘css/contentslider2.css’
});
$(“head”).append( link );

jQuery bind select change to anchor window.open variable

Thursday, April 29th, 2010

add window.open() to an anchor tag…

HTML:

select dropdown changes the source:

<div class=”name”>
<select name=”tpom” style=”float: left; width: 100px; margin-right:20px; border: 1px solid #5A3C18;” >
<option value=”downloader.php?file=folder/file.mp3″>Mp3</option>
<option value=”downloader.php?file=folder/file.zip”>Zip</option>
<option value=”downloader.php?file=folder/file.m4b”>Ipod</option>
</select>

link or button gets source from dropdown via jQuery onReady function:

$(“div.name select”).bind(“change”,function(){
$(‘#button_download’).attr(‘href’,this.value);
windowUrl = $(this).val();
//console.log(windowUrl);
});

<a onclick=”window.open(windowUrl,’download’);return false;” id=”button_download”>Download</a>

log to the console in firefox firebug javascript

Thursday, April 29th, 2010

console.log(windowUrl);

but remove it once you’ve learned what you need to as it will break things in other browsers…

session_start() php when to do it again!

Thursday, April 29th, 2010

I was stuck for a bit there.

I have a page that loads via AJAX, but I had to modify it to work for Google’s googlebot #! system…

The googlebot logic senses that it’s googlebot, and uses PHP includes instead of the AJAX!

Well the includes don’t need the session_start() again, but the AJAX loads DO!

So, NOT to be forgotten, session_start() will work per LOAD, hard to explain that, but you can wrap your head around it…

fancy!

BETTER SOLUTION: Sessions manager class, framework or similar…

jQuery scrollTo id

Monday, April 26th, 2010

<style>

.pointer { cursor: pointer; }

</style>

<a class=”pointer” onclick=”$.scrollTo(‘#here1’, 1000); return false;”>Here</a>

<h3 id=”here1″>text</h3>

<h3 id=”here2″>text</h3>

jQuery Javascript CSS gray out faded disabled element fadeTo() onload .ready()

Friday, April 23rd, 2010

Simply fade the element you’d like faded, grayed, via your .ready onload jQuery function:

$(document).ready(function() {

jQuery(‘#top_button’).fadeTo(0, 0.5);

});